diff --git a/src/SharpCompress/Archives/ArchiveVolumeFactory.cs b/src/SharpCompress/Archives/ArchiveVolumeFactory.cs index 81a5d4fd..26d7c640 100644 --- a/src/SharpCompress/Archives/ArchiveVolumeFactory.cs +++ b/src/SharpCompress/Archives/ArchiveVolumeFactory.cs @@ -13,6 +13,7 @@ internal abstract class ArchiveVolumeFactory //split 001, 002 ... var m = Regex.Match(part1.Name, @"^(.*\.)([0-9]+)$", RegexOptions.IgnoreCase); if (m.Success) + { item = new FileInfo( Path.Combine( part1.DirectoryName!, @@ -22,9 +23,13 @@ internal abstract class ArchiveVolumeFactory ) ) ); + } if (item != null && item.Exists) + { return item; + } + return null; } } diff --git a/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs b/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs index f5ce89b8..ae65d54d 100644 --- a/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs +++ b/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs @@ -13,6 +13,7 @@ internal static class RarArchiveVolumeFactory //new style rar - ..part1 | /part01 | part001 .... var m = Regex.Match(part1.Name, @"^(.*\.part)([0-9]+)(\.rar)$", RegexOptions.IgnoreCase); if (m.Success) + { item = new FileInfo( Path.Combine( part1.DirectoryName!, @@ -23,11 +24,13 @@ internal static class RarArchiveVolumeFactory ) ) ); + } else { //old style - ...rar, .r00, .r01 ... m = Regex.Match(part1.Name, @"^(.*\.)([r-z{])(ar|[0-9]+)$", RegexOptions.IgnoreCase); if (m.Success) + { item = new FileInfo( Path.Combine( part1.DirectoryName!, @@ -36,16 +39,21 @@ internal static class RarArchiveVolumeFactory index == 0 ? m.Groups[2].Value + m.Groups[3].Value : (char)(m.Groups[2].Value[0] + ((index - 1) / 100)) - + (index - 1).ToString("D4").Substring(2) + + (index - 1).ToString("D4").Substring(2) ) ) ); + } else //split .001, .002 .... + { return ArchiveVolumeFactory.GetFilePart(index, part1); + } } if (item != null && item.Exists) + { return item; + } return null; //no more items } diff --git a/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs b/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs index 1b2f093d..0f0b6517 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs @@ -14,6 +14,7 @@ internal static class ZipArchiveVolumeFactory //new style .zip, z01.. | .zipx, zx01 - if the numbers go beyond 99 then they use 100 ...1000 etc var m = Regex.Match(part1.Name, @"^(.*\.)(zipx?|zx?[0-9]+)$", RegexOptions.IgnoreCase); if (m.Success) + { item = new FileInfo( Path.Combine( part1.DirectoryName!, @@ -24,11 +25,16 @@ internal static class ZipArchiveVolumeFactory ) ) ); + } else //split - 001, 002 ... + { return ArchiveVolumeFactory.GetFilePart(index, part1); + } if (item != null && item.Exists) + { return item; + } return null; //no more items } diff --git a/src/SharpCompress/Common/Volume.cs b/src/SharpCompress/Common/Volume.cs index 54dc4995..0c4e58a1 100644 --- a/src/SharpCompress/Common/Volume.cs +++ b/src/SharpCompress/Common/Volume.cs @@ -21,7 +21,9 @@ public abstract class Volume : IVolume } if (stream is IStreamStack ss) + { ss.SetBuffer(ReaderOptions.BufferSize, true); + } _actualStream = stream; } diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 70b61bae..89d38273 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -98,7 +98,9 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory else if (_lastEntryHeader != null && _lastEntryHeader.IsZip64) { if (_lastEntryHeader.Part is null) + { continue; + } //reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation( // ref rewindableStream diff --git a/src/SharpCompress/Compressors/ArcLzw/BitReader.cs b/src/SharpCompress/Compressors/ArcLzw/BitReader.cs index 414e5e0a..ecca0907 100644 --- a/src/SharpCompress/Compressors/ArcLzw/BitReader.cs +++ b/src/SharpCompress/Compressors/ArcLzw/BitReader.cs @@ -18,13 +18,17 @@ public partial class ArcLzwStream public int? ReadBits(int bitCount) { if (bitCount <= 0 || bitCount > 16) + { throw new ArgumentOutOfRangeException( nameof(bitCount), "Bit count must be between 1 and 16" ); + } if (bytePosition >= data.Length) + { return null; + } int result = 0; int bitsRead = 0; @@ -32,7 +36,9 @@ public partial class ArcLzwStream while (bitsRead < bitCount) { if (bytePosition >= data.Length) + { return null; + } int bitsAvailable = 8 - bitPosition; int bitsToRead = Math.Min(bitCount - bitsRead, bitsAvailable); diff --git a/src/SharpCompress/Compressors/Explode/ExplodeStream.cs b/src/SharpCompress/Compressors/Explode/ExplodeStream.cs index 4b34b505..305f077a 100644 --- a/src/SharpCompress/Compressors/Explode/ExplodeStream.cs +++ b/src/SharpCompress/Compressors/Explode/ExplodeStream.cs @@ -492,7 +492,10 @@ public class ExplodeStream : Stream, IStreamStack int bitLengthOfCodes = (nextByte & 0xf) + 1; /* bits in code (1..16) */ int numOfCodes = ((nextByte & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */ if (outIndex + numOfCodes > numberExpected) + { return 4; /* don't overflow arrBitLengths[] */ + } + do { arrBitLengths[outIndex++] = bitLengthOfCodes; @@ -516,7 +519,9 @@ public class ExplodeStream : Stream, IStreamStack { bitsForLiteralCodeTable = 9; /* base table size for literals */ if ((returnCode = get_tree(arrBitLengthsForCodes, 256)) != 0) + { return returnCode; + } if ( ( @@ -531,10 +536,14 @@ public class ExplodeStream : Stream, IStreamStack ) ) != 0 ) + { return returnCode; + } if ((returnCode = get_tree(arrBitLengthsForCodes, 64)) != 0) + { return returnCode; + } if ( ( @@ -549,13 +558,17 @@ public class ExplodeStream : Stream, IStreamStack ) ) != 0 ) + { return returnCode; + } } else /* No literal tree--minimum match length is 2 */ { if ((returnCode = get_tree(arrBitLengthsForCodes, 64)) != 0) + { return returnCode; + } hufLiteralCodeTable = null; @@ -572,11 +585,15 @@ public class ExplodeStream : Stream, IStreamStack ) ) != 0 ) + { return returnCode; + } } if ((returnCode = get_tree(arrBitLengthsForCodes, 64)) != 0) + { return (int)returnCode; + } if ((generalPurposeBitFlag & HeaderFlags.Bit1) != 0) /* true if 8K */ { @@ -635,9 +652,14 @@ public class ExplodeStream : Stream, IStreamStack DumpBits(huftPointer.NumberOfBitsUsed); e = huftPointer.NumberOfExtraBits; if (e <= 32) + { break; + } + if (e == INVALID_CODE) + { return 1; + } e &= 31; NeedBits(e); @@ -690,7 +712,9 @@ public class ExplodeStream : Stream, IStreamStack out _ ) != 0 ) + { throw new Exception("Error decoding literal value"); + } nextByte = (byte)huftPointer.Value; } @@ -706,7 +730,9 @@ public class ExplodeStream : Stream, IStreamStack outBytesCount++; if (windowIndex == WSIZE) + { windowIndex = 0; + } continue; } @@ -725,7 +751,9 @@ public class ExplodeStream : Stream, IStreamStack out _ ) != 0 ) + { throw new Exception("Error decoding distance high bits"); + } distance = windowIndex - (distance + huftPointer.Value); /* construct offset */ @@ -739,7 +767,9 @@ public class ExplodeStream : Stream, IStreamStack out int extraBitLength ) != 0 ) + { throw new Exception("Error decoding coded length"); + } length = huftPointer.Value; @@ -751,7 +781,9 @@ public class ExplodeStream : Stream, IStreamStack } if (length > (unCompressedSize - outBytesCount)) + { length = (int)(unCompressedSize - outBytesCount); + } distance &= WSIZE - 1; } @@ -764,10 +796,14 @@ public class ExplodeStream : Stream, IStreamStack outBytesCount++; if (distance == WSIZE) + { distance = 0; + } if (windowIndex == WSIZE) + { windowIndex = 0; + } length--; } diff --git a/src/SharpCompress/Compressors/Explode/HuftTree.cs b/src/SharpCompress/Compressors/Explode/HuftTree.cs index d216cfc7..05094757 100644 --- a/src/SharpCompress/Compressors/Explode/HuftTree.cs +++ b/src/SharpCompress/Compressors/Explode/HuftTree.cs @@ -46,7 +46,9 @@ public static class HuftTree int[] arrBitLengthCount = new int[BMAX + 1]; for (int i = 0; i < BMAX + 1; i++) + { arrBitLengthCount[i] = 0; + } int pIndex = 0; int counterCurrentCode = numberOfCodes; @@ -64,20 +66,32 @@ public static class HuftTree /* Find minimum and maximum length, bound *outBitsForTable by those */ int counter; for (counter = 1; counter <= BMAX; counter++) + { if (arrBitLengthCount[counter] != 0) + { break; + } + } int numberOfBitsInCurrentCode = counter; /* minimum code length */ if (outBitsForTable < counter) + { outBitsForTable = counter; + } for (counterCurrentCode = BMAX; counterCurrentCode != 0; counterCurrentCode--) + { if (arrBitLengthCount[counterCurrentCode] != 0) + { break; + } + } int maximumCodeLength = counterCurrentCode; /* maximum code length */ if (outBitsForTable > counterCurrentCode) + { outBitsForTable = counterCurrentCode; + } /* Adjust last length count to fill out codes, if needed */ int numberOfDummyCodesAdded; @@ -86,11 +100,17 @@ public static class HuftTree counter < counterCurrentCode; counter++, numberOfDummyCodesAdded <<= 1 ) + { if ((numberOfDummyCodesAdded -= arrBitLengthCount[counter]) < 0) + { return 2; /* bad input: more codes than bits */ + } + } if ((numberOfDummyCodesAdded -= arrBitLengthCount[counterCurrentCode]) < 0) + { return 2; + } arrBitLengthCount[counterCurrentCode] += numberOfDummyCodesAdded; @@ -108,14 +128,18 @@ public static class HuftTree /* Make a table of values in order of bit lengths */ int[] arrValuesInOrderOfBitLength = new int[N_MAX]; for (int i = 0; i < N_MAX; i++) + { arrValuesInOrderOfBitLength[i] = 0; + } pIndex = 0; counterCurrentCode = 0; do { if ((counter = arrBitLengthForCodes[pIndex++]) != 0) + { arrValuesInOrderOfBitLength[bitOffset[counter]++] = counterCurrentCode; + } } while (++counterCurrentCode < numberOfCodes); numberOfCodes = bitOffset[maximumCodeLength]; /* set numberOfCodes to length of v */ @@ -165,7 +189,10 @@ public static class HuftTree while (++counter < numberOfEntriesInCurrentTable) /* try smaller tables up to z bits */ { if ((fBitCounter1 <<= 1) <= arrBitLengthCount[++xIndex]) + { break; /* enough codes to use up j bits */ + } + fBitCounter1 -= arrBitLengthCount[xIndex]; /* else deduct codes from patterns */ } } @@ -173,7 +200,9 @@ public static class HuftTree bitsBeforeThisTable + counter > lengthOfEOBcode && bitsBeforeThisTable < lengthOfEOBcode ) + { counter = lengthOfEOBcode - bitsBeforeThisTable; /* make EOB code end at table */ + } numberOfEntriesInCurrentTable = 1 << counter; /* table entries for j-bit table */ arrLX[stackOfBitsPerTable + tableLevel] = counter; /* set table size in stack */ @@ -216,7 +245,9 @@ public static class HuftTree }; if (pIndex >= numberOfCodes) + { vHuft1.NumberOfExtraBits = INVALID_CODE; /* out of values--invalid code */ + } else if (arrValuesInOrderOfBitLength[pIndex] < numberOfSimpleValueCodes) { vHuft1.NumberOfExtraBits = ( @@ -241,7 +272,9 @@ public static class HuftTree counter < numberOfEntriesInCurrentTable; counter += fBitCounter2 ) + { pointerToCurrentTable[counter] = vHuft1; + } /* backwards increment the k-bit code i */ for ( @@ -249,14 +282,19 @@ public static class HuftTree (counterCurrentCode & counter) != 0; counter >>= 1 ) + { counterCurrentCode ^= counter; + } + counterCurrentCode ^= counter; /* backup over finished tables */ while ( (counterCurrentCode & ((1 << bitsBeforeThisTable) - 1)) != bitOffset[tableLevel] ) + { bitsBeforeThisTable -= arrLX[stackOfBitsPerTable + (--tableLevel)]; + } } } diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs index 24f5ab17..c701a5b5 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs @@ -30,7 +30,9 @@ internal class BCJFilterARM64 : Filter pc >>= 2; if (!_isEncoder) + { pc = 0U - pc; + } instr |= (src + pc) & 0x03FFFFFF; BinaryPrimitives.WriteUInt32LittleEndian(new Span(buffer, i, 4), instr); @@ -40,13 +42,17 @@ internal class BCJFilterARM64 : Filter uint src = ((instr >> 29) & 3) | ((instr >> 3) & 0x001FFFFC); if (((src + 0x00020000) & 0x001C0000) != 0) + { continue; + } instr &= 0x9000001F; pc >>= 12; if (!_isEncoder) + { pc = 0U - pc; + } uint dest = src + pc; instr |= (dest & 3) << 29; diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs index db5b36f2..89954f56 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs @@ -27,9 +27,13 @@ internal class BCJFilterARMT : Filter int dest; if (_isEncoder) + { dest = src + (_pos + i - offset); + } else + { dest = src - (_pos + i - offset); + } dest >>>= 1; buffer[i + 1] = (byte)(0xF0 | ((dest >>> 19) & 0x07)); diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs b/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs index 44323ae7..80d308a3 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs @@ -58,7 +58,9 @@ internal class BCJFilterIA64 : Filter for (int slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41) { if (((mask >>> slot) & 1) == 0) + { continue; + } var bytePos = bitPos >>> 3; var bitRes = bitPos & 7; @@ -72,7 +74,9 @@ internal class BCJFilterIA64 : Filter var instrNorm = instr >>> bitRes; if (((instrNorm >>> 37) & 0x0F) != 0x05 || ((instrNorm >>> 9) & 0x07) != 0x00) + { continue; + } var src = (int)((instrNorm >>> 13) & 0x0FFFFF); src |= ((int)(instrNorm >>> 36) & 1) << 20; @@ -80,9 +84,13 @@ internal class BCJFilterIA64 : Filter int dest; if (_isEncoder) + { dest = src + (_pos + i - offset); + } else + { dest = src - (_pos + i - offset); + } dest >>>= 4; diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs b/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs index 67d9cb52..32ad6ea2 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs @@ -27,7 +27,9 @@ internal class BCJFilterRISCV : Filter { uint b1 = buffer[i + 1]; if ((b1 & 0x0D) != 0) + { continue; + } uint b2 = buffer[i + 2]; uint b3 = buffer[i + 3]; @@ -116,7 +118,9 @@ internal class BCJFilterRISCV : Filter { uint b1 = buffer[i + 1]; if ((b1 & 0x0D) != 0) + { continue; + } uint b2 = buffer[i + 2]; uint b3 = buffer[i + 3]; diff --git a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs index df95c838..bbe91196 100644 --- a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs +++ b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs @@ -47,13 +47,17 @@ public sealed class BranchExecFilter var size = (uint)buf.Length; if (size <= 4) + { return; + } size -= 4; for (i = 0; i < size; ++i) { if ((buf[i] & 0xFE) != 0xE8) + { continue; + } prev_pos = i - prev_pos; if (prev_pos > 3) @@ -89,12 +93,16 @@ public sealed class BranchExecFilter { dest = src - (pos + (uint)i + 5); if (prev_mask == 0) + { break; + } j = mask_to_bit_num[prev_mask] * 8u; b = (byte)(dest >> (24 - (int)j)); if (!X86TestByte(b)) + { break; + } src = dest ^ ((1u << (32 - (int)j)) - 1u); } diff --git a/src/SharpCompress/Compressors/Lzw/LzwStream.cs b/src/SharpCompress/Compressors/Lzw/LzwStream.cs index 1dd2736f..36f283e9 100644 --- a/src/SharpCompress/Compressors/Lzw/LzwStream.cs +++ b/src/SharpCompress/Compressors/Lzw/LzwStream.cs @@ -75,7 +75,9 @@ public class LzwStream : Stream, IStreamStack // Check the magic marker if (result < 0) + { throw new IncompleteArchiveException("Failed to read LZW header"); + } if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) { @@ -124,7 +126,10 @@ public class LzwStream : Stream, IStreamStack { int b = Read(one, 0, 1); if (b == 1) + { return (one[0] & 0xff); + } + return -1; } @@ -144,10 +149,14 @@ public class LzwStream : Stream, IStreamStack public override int Read(byte[] buffer, int offset, int count) { if (!headerParsed) + { ParseHeader(); + } if (eof) + { return 0; + } int start = offset; @@ -251,7 +260,9 @@ public class LzwStream : Stream, IStreamStack if (lOldCode == -1) { if (code >= 256) + { throw new IncompleteArchiveException("corrupt input: " + code + " > 255"); + } lFinChar = (byte)(lOldCode = code); buffer[offset++] = lFinChar; @@ -400,7 +411,9 @@ public class LzwStream : Stream, IStreamStack // Check the magic marker if (result < 0) + { throw new IncompleteArchiveException("Failed to read LZW header"); + } if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) { @@ -448,7 +461,9 @@ public class LzwStream : Stream, IStreamStack stackP = stack.Length; for (int idx = 255; idx >= 0; idx--) + { tabSuffix[idx] = (byte)idx; + } } #region Stream Overrides diff --git a/src/SharpCompress/Compressors/Reduce/ReduceStream.cs b/src/SharpCompress/Compressors/Reduce/ReduceStream.cs index 8ea0cd3d..ea8e70d2 100644 --- a/src/SharpCompress/Compressors/Reduce/ReduceStream.cs +++ b/src/SharpCompress/Compressors/Reduce/ReduceStream.cs @@ -140,7 +140,10 @@ public class ReduceStream : Stream, IStreamStack private int NEXTBYTE() { if (inByteCount == compressedSize) + { return EOF; + } + inByteCount++; return inStream.ReadByte(); } @@ -229,7 +232,9 @@ public class ReduceStream : Stream, IStreamStack windowsBuffer[windowIndex++] = nextByte; outBytesCount++; if (windowIndex == WSIZE) + { windowIndex = 0; + } continue; } @@ -241,7 +246,9 @@ public class ReduceStream : Stream, IStreamStack windowsBuffer[windowIndex++] = RunLengthCode; outBytesCount++; if (windowIndex == WSIZE) + { windowIndex = 0; + } continue; } @@ -268,10 +275,14 @@ public class ReduceStream : Stream, IStreamStack outBytesCount++; if (distance == WSIZE) + { distance = 0; + } if (windowIndex == WSIZE) + { windowIndex = 0; + } length--; } diff --git a/src/SharpCompress/Compressors/Squeezed/BitReader.cs b/src/SharpCompress/Compressors/Squeezed/BitReader.cs index 123acfb5..04d7b7e6 100644 --- a/src/SharpCompress/Compressors/Squeezed/BitReader.cs +++ b/src/SharpCompress/Compressors/Squeezed/BitReader.cs @@ -20,7 +20,10 @@ public class BitReader { int nextByte = _stream.ReadByte(); if (nextByte == -1) + { throw new EndOfStreamException(); + } + _bitBuffer = nextByte; _bitCount = 8; } diff --git a/src/SharpCompress/IO/SharpCompressStream.cs b/src/SharpCompress/IO/SharpCompressStream.cs index 6d7d5372..1e0c3d61 100644 --- a/src/SharpCompress/IO/SharpCompressStream.cs +++ b/src/SharpCompress/IO/SharpCompressStream.cs @@ -72,7 +72,10 @@ public class SharpCompressStream : Stream, IStreamStack if (_bufferingEnabled) { if (value < 0 || value > _bufferedLength) + { throw new ArgumentOutOfRangeException(nameof(value)); + } + _internalPosition = value; _bufferPosition = value; ValidateBufferState(); // Add here @@ -112,7 +115,10 @@ public class SharpCompressStream : Stream, IStreamStack ) { if (bufferSize != 0) + { ((IStreamStack)stream).SetBuffer(bufferSize, forceBuffer); + } + return sc; } return new SharpCompressStream(stream, leaveOpen, throwOnDispose, bufferSize, forceBuffer); @@ -205,7 +211,9 @@ public class SharpCompressStream : Stream, IStreamStack public override int Read(byte[] buffer, int offset, int count) { if (count == 0) + { return 0; + } if (_bufferingEnabled) { @@ -229,7 +237,10 @@ public class SharpCompressStream : Stream, IStreamStack // If buffer exhausted, refill int r = Stream.Read(_buffer!, 0, _bufferSize); if (r == 0) + { return 0; + } + _bufferedLength = r; _bufferPosition = 0; if (_bufferedLength == 0) diff --git a/src/SharpCompress/IO/StackStreamExtensions.cs b/src/SharpCompress/IO/StackStreamExtensions.cs index 5e98a587..211bf3fb 100644 --- a/src/SharpCompress/IO/StackStreamExtensions.cs +++ b/src/SharpCompress/IO/StackStreamExtensions.cs @@ -15,7 +15,7 @@ internal static class StackStreamExtensions /// The position of the first buffering stream, or 0 if not found. internal static long GetPosition(this IStreamStack stream) { - IStreamStack? current = stream; + var current = stream; while (current != null) { @@ -23,7 +23,7 @@ internal static class StackStreamExtensions { return st.Position; } - current = current?.BaseStream() as IStreamStack; + current = current.BaseStream() as IStreamStack; } return 0; } @@ -36,10 +36,8 @@ internal static class StackStreamExtensions /// The number of bytes to rewind within the buffer. internal static void Rewind(this IStreamStack stream, int count) { - Stream baseStream = stream.BaseStream(); - Stream thisStream = (Stream)stream; IStreamStack? buffStream = null; - IStreamStack? current = stream; + var current = stream; while (buffStream == null && current != null) { @@ -62,10 +60,12 @@ internal static class StackStreamExtensions internal static void SetBuffer(this IStreamStack stream, int bufferSize, bool force) { if (bufferSize == 0 || stream == null) + { return; + } - IStreamStack? current = stream; - IStreamStack defaultBuffer = stream; + var current = stream; + var defaultBuffer = stream; IStreamStack? buffer = null; // First pass: find the deepest IStreamStack @@ -73,13 +73,22 @@ internal static class StackStreamExtensions { defaultBuffer = current; if (buffer == null && ((current.BufferSize != 0 && bufferSize != 0) || force)) + { buffer = current; + } + if (defaultBuffer.DefaultBufferSize != 0) + { break; + } + current = current.BaseStream() as IStreamStack; } if (defaultBuffer.DefaultBufferSize == 0) + { defaultBuffer.DefaultBufferSize = bufferSize; + } + (buffer ?? stream).BufferSize = bufferSize; } @@ -98,9 +107,8 @@ internal static class StackStreamExtensions internal static long StackSeek(this IStreamStack stream, long position) { var stack = new List(); - Stream? current = stream as Stream; - int lastBufferingIndex = -1; - int firstSeekableIndex = -1; + var current = stream as Stream; + var lastBufferingIndex = -1; Stream? firstSeekableStream = null; // Traverse the stack, collecting info @@ -118,7 +126,6 @@ internal static class StackStreamExtensions // Find the first seekable stream (closest to the root) if (current != null && current.CanSeek) { - firstSeekableIndex = stack.Count; firstSeekableStream = current; } @@ -171,9 +178,9 @@ internal static class StackStreamExtensions out int baseReadCount ) { - Stream baseStream = stream.BaseStream(); - Stream thisStream = (Stream)stream; - IStreamStack? current = stream; + var baseStream = stream.BaseStream(); + var thisStream = (Stream)stream; + var current = stream; buffStream = null; baseReadCount = -1; @@ -185,9 +192,9 @@ internal static class StackStreamExtensions } } - long buffPos = buffStream == null ? -1 : ((Stream)buffStream).Position; + var buffPos = buffStream == null ? -1 : ((Stream)buffStream).Position; - int read = baseStream.Read(buffer, offset, count); //amount read in to buffer + var read = baseStream.Read(buffer, offset, count); //amount read in to buffer if (buffPos != -1) { @@ -202,7 +209,10 @@ internal static class StackStreamExtensions private static string cleansePos(long pos) { if (pos < 0) + { return ""; + } + return "Px" + pos.ToString("x"); } @@ -216,7 +226,10 @@ internal static class StackStreamExtensions public static long GetInstanceId(this IStreamStack stream, ref long instanceId, bool construct) { if (instanceId == 0) //will not be equal to 0 when inherited IStackStream types are being used + { instanceId = System.Threading.Interlocked.Increment(ref _instanceCounter); + } + return instanceId; } @@ -227,15 +240,17 @@ internal static class StackStreamExtensions /// The type being constructed. public static void DebugConstruct(this IStreamStack stream, Type constructing) { - long id = stream.InstanceId; + var id = stream.InstanceId; stream.InstanceId = GetInstanceId(stream, ref id, true); var frame = (new StackTrace()).GetFrame(3); - string parentInfo = + var parentInfo = frame != null ? $"{frame.GetMethod()?.DeclaringType?.Name}.{frame.GetMethod()?.Name}()" : "Unknown"; if (constructing.FullName == stream.GetType().FullName) //don't debug base IStackStream types + { Debug.WriteLine($"{GetStreamStackString(stream, true)} : Constructed by [{parentInfo}]"); + } } /// @@ -246,12 +261,14 @@ internal static class StackStreamExtensions public static void DebugDispose(this IStreamStack stream, Type constructing) { var frame = (new StackTrace()).GetFrame(3); - string parentInfo = + var parentInfo = frame != null ? $"{frame.GetMethod()?.DeclaringType?.Name}.{frame.GetMethod()?.Name}()" : "Unknown"; if (constructing.FullName == stream.GetType().FullName) //don't debug base IStackStream types + { Debug.WriteLine($"{GetStreamStackString(stream, false)} : Disposed by [{parentInfo}]"); + } } /// @@ -275,17 +292,20 @@ internal static class StackStreamExtensions public static string GetStreamStackString(this IStreamStack stream, bool construct) { var sb = new StringBuilder(); - Stream? current = stream as Stream; + var current = stream as Stream; while (current != null) { - IStreamStack? sStack = current as IStreamStack; - string id = sStack != null ? "#" + sStack.InstanceId.ToString() : ""; - string buffSize = sStack != null ? "Bx" + sStack.BufferSize.ToString("x") : ""; - string defBuffSize = + var sStack = current as IStreamStack; + var id = sStack != null ? "#" + sStack.InstanceId.ToString() : ""; + var buffSize = sStack != null ? "Bx" + sStack.BufferSize.ToString("x") : ""; + var defBuffSize = sStack != null ? "Dx" + sStack.DefaultBufferSize.ToString("x") : ""; if (sb.Length > 0) + { sb.Insert(0, "/"); + } + try { sb.Insert( @@ -296,17 +316,25 @@ internal static class StackStreamExtensions catch { if (current is SharpCompressStream scs) + { sb.Insert( 0, $"{current.GetType().Name}{id}[{cleansePos(scs.InternalPosition)}:{buffSize}:{defBuffSize}]" ); + } else + { sb.Insert(0, $"{current.GetType().Name}{id}[:{buffSize}]"); + } } if (sStack != null) + { current = sStack.BaseStream(); //current may not be a IStreamStack, allow one more loop + } else + { break; + } } return sb.ToString(); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs b/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs index 9aa80dd1..524ea7eb 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs @@ -46,10 +46,12 @@ public class ZipWriterOptions : WriterOptions public void SetZStandardCompressionLevel(int level) { if (level < 1 || level > 22) + { throw new ArgumentOutOfRangeException( nameof(level), "ZStandard compression level must be between 1 and 22" ); + } CompressionLevel = level; }