From: buyaa-n Date: Fri, 27 Sep 2019 16:41:52 +0000 (-0700) Subject: Annotate System.IO.Compression for nullable (dotnet/corefx#41322) X-Git-Tag: submit/tizen/20210909.063632~11031^2~395 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=69feffca5297bc3c887325a7ea3022ae55850466;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Annotate System.IO.Compression for nullable (dotnet/corefx#41322) Nullable annotation for System.IO.Compression Commit migrated from https://github.com/dotnet/corefx/commit/967eb3c5cb5fd36c8bb56d06f4c840f6a7a5a754 --- diff --git a/src/libraries/Common/src/System/IO/PathInternal.Windows.cs b/src/libraries/Common/src/System/IO/PathInternal.Windows.cs index a697899..1287b56 100644 --- a/src/libraries/Common/src/System/IO/PathInternal.Windows.cs +++ b/src/libraries/Common/src/System/IO/PathInternal.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; namespace System.IO @@ -73,7 +74,8 @@ namespace System.IO /// away from paths during normalization, but if we see such a path at this point it should be /// normalized and has retained the final characters. (Typically from one of the *Info classes) /// - internal static string EnsureExtendedPrefixIfNeeded(string path) + /// TODO: add atribute [return: NotNullIfNotNull("path")] + internal static string? EnsureExtendedPrefixIfNeeded(string? path) { if (path != null && (path.Length >= MaxShortPath || EndsWithPeriodOrSpace(path))) { diff --git a/src/libraries/System.IO.Compression/ref/System.IO.Compression.cs b/src/libraries/System.IO.Compression/ref/System.IO.Compression.cs index 0168c11..fbea7cc 100644 --- a/src/libraries/System.IO.Compression/ref/System.IO.Compression.cs +++ b/src/libraries/System.IO.Compression/ref/System.IO.Compression.cs @@ -30,8 +30,8 @@ namespace System.IO.Compression public override bool CanWrite { get { throw null; } } public override long Length { get { throw null; } } public override long Position { get { throw null; } set { } } - public override System.IAsyncResult BeginRead(byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) { throw null; } - public override System.IAsyncResult BeginWrite(byte[] array, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) { throw null; } + public override System.IAsyncResult BeginRead(byte[] buffer, int offset, int count, System.AsyncCallback? asyncCallback, object? asyncState) { throw null; } + public override System.IAsyncResult BeginWrite(byte[] array, int offset, int count, System.AsyncCallback? asyncCallback, object? asyncState) { throw null; } public override void CopyTo(System.IO.Stream destination, int bufferSize) { } public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) { throw null; } protected override void Dispose(bool disposing) { } @@ -64,8 +64,8 @@ namespace System.IO.Compression public override bool CanWrite { get { throw null; } } public override long Length { get { throw null; } } public override long Position { get { throw null; } set { } } - public override System.IAsyncResult BeginRead(byte[] array, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) { throw null; } - public override System.IAsyncResult BeginWrite(byte[] array, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) { throw null; } + public override System.IAsyncResult BeginRead(byte[] array, int offset, int count, System.AsyncCallback? asyncCallback, object? asyncState) { throw null; } + public override System.IAsyncResult BeginWrite(byte[] array, int offset, int count, System.AsyncCallback? asyncCallback, object? asyncState) { throw null; } public override void CopyTo(System.IO.Stream destination, int bufferSize) { } public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) { throw null; } protected override void Dispose(bool disposing) { } @@ -91,14 +91,14 @@ namespace System.IO.Compression public ZipArchive(System.IO.Stream stream) { } public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode) { } public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen) { } - public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen, System.Text.Encoding entryNameEncoding) { } + public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen, System.Text.Encoding? entryNameEncoding) { } public System.Collections.ObjectModel.ReadOnlyCollection Entries { get { throw null; } } public System.IO.Compression.ZipArchiveMode Mode { get { throw null; } } public System.IO.Compression.ZipArchiveEntry CreateEntry(string entryName) { throw null; } public System.IO.Compression.ZipArchiveEntry CreateEntry(string entryName, System.IO.Compression.CompressionLevel compressionLevel) { throw null; } public void Dispose() { } protected virtual void Dispose(bool disposing) { } - public System.IO.Compression.ZipArchiveEntry GetEntry(string entryName) { throw null; } + public System.IO.Compression.ZipArchiveEntry? GetEntry(string entryName) { throw null; } } public partial class ZipArchiveEntry { diff --git a/src/libraries/System.IO.Compression/ref/System.IO.Compression.csproj b/src/libraries/System.IO.Compression/ref/System.IO.Compression.csproj index 108d194..21eac72 100644 --- a/src/libraries/System.IO.Compression/ref/System.IO.Compression.csproj +++ b/src/libraries/System.IO.Compression/ref/System.IO.Compression.csproj @@ -1,6 +1,7 @@ netcoreapp-Debug;netcoreapp-Release;uap-Debug;uap-Release + enable diff --git a/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj b/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj index 70bf5a4..0b2204a 100644 --- a/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj +++ b/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj @@ -4,6 +4,7 @@ Library true netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release + enable @@ -16,7 +17,6 @@ - diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateInput.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateInput.cs deleted file mode 100644 index 64d793d..0000000 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateInput.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Diagnostics; - -namespace System.IO.Compression -{ - internal sealed class DeflateInput - { - internal byte[] Buffer { get; set; } - internal int Count { get; set; } - internal int StartIndex { get; set; } - - internal void ConsumeBytes(int n) - { - Debug.Assert(n <= Count, "Should use more bytes than what we have in the buffer"); - StartIndex += n; - Count -= n; - Debug.Assert(StartIndex + Count <= Buffer.Length, "Input buffer is in invalid state!"); - } - - internal InputState DumpState() => new InputState(Count, StartIndex); - - internal void RestoreState(InputState state) - { - Count = state._count; - StartIndex = state._startIndex; - } - - internal readonly struct InputState - { - internal readonly int _count; - internal readonly int _startIndex; - - internal InputState(int count, int startIndex) - { - _count = count; - _startIndex = startIndex; - } - } - } -} diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs index dfadee5..df53b22 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs @@ -14,38 +14,27 @@ namespace System.IO.Compression { internal const int DefaultBufferSize = 8192; - private Stream _stream; - private bool _leaveOpen; + private Stream? _stream; private InflaterManaged _inflater; - private byte[] _buffer; + private readonly byte[] _buffer; private int _asyncOperations; // A specific constructor to allow decompression of Deflate64 - internal DeflateManagedStream(Stream stream, ZipArchiveEntry.CompressionMethodValues method, long uncompressedSize) + internal DeflateManagedStream(Stream stream, ZipArchiveEntry.CompressionMethodValues method, long uncompressedSize = -1) { if (stream == null) throw new ArgumentNullException(nameof(stream)); if (!stream.CanRead) throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); - - InitializeInflater(stream, false, null, method, uncompressedSize); - } - - /// - /// Sets up this DeflateManagedStream to be used for Inflation/Decompression - /// - internal void InitializeInflater(Stream stream, bool leaveOpen, IFileFormatReader reader = null, ZipArchiveEntry.CompressionMethodValues method = ZipArchiveEntry.CompressionMethodValues.Deflate, long uncompressedSize = -1) - { - Debug.Assert(stream != null); - Debug.Assert(method == ZipArchiveEntry.CompressionMethodValues.Deflate64); if (!stream.CanRead) throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); - _inflater = new InflaterManaged(reader, method == ZipArchiveEntry.CompressionMethodValues.Deflate64 ? true : false, uncompressedSize); + Debug.Assert(method == ZipArchiveEntry.CompressionMethodValues.Deflate64); + + _inflater = new InflaterManaged(null, method == ZipArchiveEntry.CompressionMethodValues.Deflate64 ? true : false, uncompressedSize); _stream = stream; - _leaveOpen = leaveOpen; _buffer = new byte[DefaultBufferSize]; } @@ -133,7 +122,7 @@ namespace System.IO.Compression break; } - int bytes = _stream.Read(_buffer, 0, _buffer.Length); + int bytes = _stream!.Read(_buffer, 0, _buffer.Length); if (bytes <= 0) { break; @@ -177,7 +166,7 @@ namespace System.IO.Compression throw new ObjectDisposedException(null, SR.ObjectDisposed_StreamClosed); } - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) => + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) => TaskToApm.Begin(ReadAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState); public override int EndRead(IAsyncResult asyncResult) => @@ -198,7 +187,7 @@ namespace System.IO.Compression } Interlocked.Increment(ref _asyncOperations); - Task readTask = null; + Task? readTask = null; try { @@ -218,7 +207,7 @@ namespace System.IO.Compression // If there is no data on the output buffer and we are not at // the end of the stream, we need to get more data from the base stream - readTask = _stream.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken); + readTask = _stream!.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken); if (readTask == null) { throw new InvalidOperationException(SR.NotSupported_UnreadableStream); @@ -267,7 +256,7 @@ namespace System.IO.Compression { // We could have read in head information and didn't get any data. // Read from the base stream again. - readTask = _stream.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken); + readTask = _stream!.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken); if (readTask == null) { throw new InvalidOperationException(SR.NotSupported_UnreadableStream); @@ -315,12 +304,12 @@ namespace System.IO.Compression // In this case, we still need to clean up internal resources, hence the inner finally blocks. try { - if (disposing && !_leaveOpen && _stream != null) + if (disposing && _stream != null) _stream.Dispose(); } finally { - _stream = null; + _stream = null!; try { @@ -328,7 +317,7 @@ namespace System.IO.Compression } finally { - _inflater = null; + _inflater = null!; base.Dispose(disposing); } } diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs index fd031a6..2a4cee8 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs @@ -34,7 +34,7 @@ namespace System.IO.Compression private readonly short[] _right; private readonly byte[] _codeLengthArray; #if DEBUG - private uint[] _codeArrayDebug; + private uint[]? _codeArrayDebug; #endif private readonly int _tableMask; diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs index e735ca1..d88e253 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs @@ -45,8 +45,8 @@ namespace System.IO.Compression private readonly OutputWindow _output; private readonly InputBuffer _input; - private HuffmanTree _literalLengthTree; - private HuffmanTree _distanceTree; + private HuffmanTree? _literalLengthTree; + private HuffmanTree? _distanceTree; private InflaterState _state; private readonly bool _hasFormatReader; @@ -72,13 +72,13 @@ namespace System.IO.Compression private readonly byte[] _codeList; // temporary array to store the code length for literal/Length and distance private readonly byte[] _codeLengthTreeCodeLength; private readonly bool _deflate64; - private HuffmanTree _codeLengthTree; + private HuffmanTree? _codeLengthTree; private readonly long _uncompressedSize; private long _currentInflatedCount; - private readonly IFileFormatReader _formatReader; // class to decode header and footer (e.g. gzip) + private readonly IFileFormatReader? _formatReader; // class to decode header and footer (e.g. gzip) - internal InflaterManaged(IFileFormatReader reader, bool deflate64, long uncompressedSize) + internal InflaterManaged(IFileFormatReader? reader, bool deflate64, long uncompressedSize) { _output = new OutputWindow(); _input = new InputBuffer(); @@ -140,6 +140,7 @@ namespace System.IO.Compression { if (_hasFormatReader) { + Debug.Assert(_formatReader != null); _formatReader.UpdateWithBytesRead(bytes, offset, copied); } @@ -161,6 +162,7 @@ namespace System.IO.Compression // But some data in output window might not be copied out. if (_output.AvailableBytes == 0) { + Debug.Assert(_formatReader != null); _formatReader.Validate(); } } @@ -201,6 +203,7 @@ namespace System.IO.Compression if (_hasFormatReader) { + Debug.Assert(_formatReader != null); if (_state == InflaterState.ReadingHeader) { if (!_formatReader.ReadHeader(_input)) @@ -398,6 +401,7 @@ namespace System.IO.Compression case InflaterState.DecodeTop: // decode an element from the literal tree + Debug.Assert(_literalLengthTree != null); // TODO: optimize this!!! symbol = _literalLengthTree.GetNextSymbol(_input); if (symbol < 0) @@ -471,6 +475,7 @@ namespace System.IO.Compression case InflaterState.HaveFullLength: if (_blockType == BlockType.Dynamic) { + Debug.Assert(_distanceTree != null); _distanceCode = _distanceTree.GetNextSymbol(_input); } else @@ -615,6 +620,7 @@ namespace System.IO.Compression { if (_state == InflaterState.ReadingTreeCodesBefore) { + Debug.Assert(_codeLengthTree != null); if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0) { return false; diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InputBuffer.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InputBuffer.cs index e17b2e8..13efb3e 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InputBuffer.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InputBuffer.cs @@ -18,7 +18,7 @@ namespace System.IO.Compression internal sealed class InputBuffer { - private byte[] _buffer; // byte array to store input + private byte[]? _buffer; // byte array to store input private int _start; // start poisition of the buffer private int _end; // end position of the buffer private uint _bitBuffer = 0; // store the bits here, we can quickly shift in this buffer @@ -44,6 +44,7 @@ namespace System.IO.Compression { return false; } + Debug.Assert(_buffer != null); // insert a byte to bitbuffer _bitBuffer |= (uint)_buffer[_start++] << _bitsInBuffer; _bitsInBuffer += 8; @@ -72,6 +73,7 @@ namespace System.IO.Compression /// public uint TryLoad16Bits() { + Debug.Assert(_buffer != null); if (_bitsInBuffer < 8) { if (_start < _end) @@ -152,6 +154,7 @@ namespace System.IO.Compression length = avail; } + Debug.Assert(_buffer != null); Array.Copy(_buffer, _start, output, offset, length); _start += length; return bytesFromBitBuffer + length; diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs index f09f827..9416b37 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs @@ -14,12 +14,12 @@ namespace System.IO.Compression { private const int DefaultBufferSize = 8192; - private Stream _stream; + private Stream _stream = null!; // field initialized in init methods called from constructor private CompressionMode _mode; private bool _leaveOpen; - private Inflater _inflater; - private Deflater _deflater; - private byte[] _buffer; + private Inflater? _inflater; + private Deflater? _deflater; + private byte[]? _buffer; private int _activeAsyncOperation; // 1 == true, 0 == false private bool _wroteBytes; @@ -57,7 +57,13 @@ namespace System.IO.Compression switch (mode) { case CompressionMode.Decompress: - InitializeInflater(stream, leaveOpen, windowBits, uncompressedSize); + if (!stream.CanRead) + throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); + + _inflater = new Inflater(windowBits, uncompressedSize); + _stream = stream; + _mode = CompressionMode.Decompress; + _leaveOpen = leaveOpen; break; case CompressionMode.Compress: @@ -81,22 +87,6 @@ namespace System.IO.Compression } /// - /// Sets up this DeflateStream to be used for Zlib Inflation/Decompression - /// - internal void InitializeInflater(Stream stream, bool leaveOpen, int windowBits, long uncompressedSize) - { - Debug.Assert(stream != null); - if (!stream.CanRead) - throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); - - _inflater = new Inflater(windowBits, uncompressedSize); - - _stream = stream; - _mode = CompressionMode.Decompress; - _leaveOpen = leaveOpen; - } - - /// /// Sets up this DeflateStream to be used for Zlib Deflation/Compression /// internal void InitializeDeflater(Stream stream, bool leaveOpen, int windowBits, CompressionLevel compressionLevel) @@ -191,6 +181,7 @@ namespace System.IO.Compression AsyncOperationStarting(); try { + Debug.Assert(_deflater != null && _buffer != null); // Compress any bytes left: await WriteDeflaterOutputAsync(cancellationToken).ConfigureAwait(false); @@ -231,6 +222,7 @@ namespace System.IO.Compression // Try to read a single byte from zlib without allocating an array, pinning an array, etc. // If zlib doesn't have any data, fall back to the base stream implementation, which will do that. byte b; + Debug.Assert(_inflater != null); return _inflater.Inflate(out b) ? b : base.ReadByte(); } @@ -263,6 +255,7 @@ namespace System.IO.Compression int totalRead = 0; + Debug.Assert(_inflater != null); while (true) { int bytesRead = _inflater.Inflate(buffer.Slice(totalRead)); @@ -283,6 +276,7 @@ namespace System.IO.Compression if (_inflater.NeedsInput()) { + Debug.Assert(_buffer != null); int bytes = _stream.Read(_buffer, 0, _buffer.Length); if (bytes <= 0) { @@ -350,7 +344,7 @@ namespace System.IO.Compression throw new InvalidOperationException(SR.CannotWriteToDeflateStream); } - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) => + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) => TaskToApm.Begin(ReadAsync(buffer, offset, count, CancellationToken.None), asyncCallback, asyncState); public override int EndRead(IAsyncResult asyncResult) => @@ -393,6 +387,7 @@ namespace System.IO.Compression AsyncOperationStarting(); try { + Debug.Assert(_inflater != null); while (true) { // Finish inflating any bytes in the input buffer @@ -443,6 +438,7 @@ namespace System.IO.Compression { try { + Debug.Assert(_inflater != null && _buffer != null); while (true) { if (_inflater.NeedsInput()) @@ -531,6 +527,7 @@ namespace System.IO.Compression EnsureCompressionMode(); EnsureNotDisposed(); + Debug.Assert(_deflater != null); // Write compressed the bytes we already passed to the deflater: WriteDeflaterOutput(); @@ -548,6 +545,7 @@ namespace System.IO.Compression private void WriteDeflaterOutput() { + Debug.Assert(_deflater != null && _buffer != null); while (!_deflater.NeedsInput()) { int compressedBytes = _deflater.GetDeflateOutput(_buffer); @@ -567,6 +565,7 @@ namespace System.IO.Compression // Compress any bytes left: WriteDeflaterOutput(); + Debug.Assert(_deflater != null && _buffer != null); // Pull out any bytes left inside deflater: bool flushSuccessful; do @@ -594,6 +593,7 @@ namespace System.IO.Compression if (_mode != CompressionMode.Compress) return; + Debug.Assert(_deflater != null && _buffer != null); // Some deflaters (e.g. ZLib) write more than zero bytes for zero byte inputs. // This round-trips and we should be ok with this, but our legacy managed deflater // always wrote zero output for zero input and upstack code (e.g. ZipArchiveEntry) @@ -641,6 +641,7 @@ namespace System.IO.Compression if (_mode != CompressionMode.Compress) return; + Debug.Assert(_deflater != null && _buffer != null); // Some deflaters (e.g. ZLib) write more than zero bytes for zero byte inputs. // This round-trips and we should be ok with this, but our legacy managed deflater // always wrote zero output for zero input and upstack code (e.g. ZipArchiveEntry) @@ -696,7 +697,7 @@ namespace System.IO.Compression } finally { - _stream = null; + _stream = null!; try { @@ -708,7 +709,7 @@ namespace System.IO.Compression _deflater = null; _inflater = null; - byte[] buffer = _buffer; + byte[]? buffer = _buffer; if (buffer != null) { _buffer = null; @@ -744,7 +745,7 @@ namespace System.IO.Compression // Stream.Close() may throw here (may or may not be due to the same error). // In this case, we still need to clean up internal resources, hence the inner finally blocks. Stream stream = _stream; - _stream = null; + _stream = null!; try { if (!_leaveOpen && stream != null) @@ -762,7 +763,7 @@ namespace System.IO.Compression _deflater = null; _inflater = null; - byte[] buffer = _buffer; + byte[]? buffer = _buffer; if (buffer != null) { _buffer = null; @@ -776,7 +777,7 @@ namespace System.IO.Compression } } - public override IAsyncResult BeginWrite(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState) => + public override IAsyncResult BeginWrite(byte[] array, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) => TaskToApm.Begin(WriteAsync(array, offset, count, CancellationToken.None), asyncCallback, asyncState); public override void EndWrite(IAsyncResult asyncResult) => @@ -820,6 +821,7 @@ namespace System.IO.Compression { await WriteDeflaterOutputAsync(cancellationToken).ConfigureAwait(false); + Debug.Assert(_deflater != null); // Pass new bytes through deflater _deflater.SetInput(buffer); @@ -838,6 +840,7 @@ namespace System.IO.Compression /// private async Task WriteDeflaterOutputAsync(CancellationToken cancellationToken) { + Debug.Assert(_deflater != null && _buffer != null); while (!_deflater.NeedsInput()) { int compressedBytes = _deflater.GetDeflateOutput(_buffer); @@ -907,6 +910,7 @@ namespace System.IO.Compression _deflateStream.AsyncOperationStarting(); try { + Debug.Assert(_deflateStream._inflater != null); // Flush any existing data in the inflater to the destination stream. while (!_deflateStream._inflater.Finished()) { @@ -930,7 +934,7 @@ namespace System.IO.Compression _deflateStream.AsyncOperationCompleting(); ArrayPool.Shared.Return(_arrayPoolBuffer); - _arrayPoolBuffer = null; + _arrayPoolBuffer = null!; } } @@ -938,6 +942,7 @@ namespace System.IO.Compression { try { + Debug.Assert(_deflateStream._inflater != null); // Flush any existing data in the inflater to the destination stream. while (!_deflateStream._inflater.Finished()) { @@ -959,7 +964,7 @@ namespace System.IO.Compression finally { ArrayPool.Shared.Return(_arrayPoolBuffer); - _arrayPoolBuffer = null; + _arrayPoolBuffer = null!; } } @@ -979,6 +984,7 @@ namespace System.IO.Compression throw new InvalidDataException(SR.GenericInvalidData); } + Debug.Assert(_deflateStream._inflater != null); // Feed the data from base stream into the decompression engine. _deflateStream._inflater.SetInput(buffer, offset, count); @@ -1015,6 +1021,7 @@ namespace System.IO.Compression throw new InvalidDataException(SR.GenericInvalidData); } + Debug.Assert(_deflateStream._inflater != null); // Feed the data from base stream into the decompression engine. _deflateStream._inflater.SetInput(buffer, offset, count); diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs index 4ad5a68..e7721dc 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Deflater.cs @@ -16,7 +16,7 @@ namespace System.IO.Compression /// internal sealed class Deflater : IDisposable { - private ZLibNative.ZLibStreamHandle _zlibStream; + private readonly ZLibNative.ZLibStreamHandle _zlibStream; private MemoryHandle _inputBufferHandle; private bool _isDisposed; private const int minWindowBits = -15; // WindowBits must be between -8..-15 to write no header, 8..15 for a @@ -60,7 +60,34 @@ namespace System.IO.Compression ZLibNative.CompressionStrategy strategy = ZLibNative.CompressionStrategy.DefaultStrategy; - DeflateInit(zlibCompressionLevel, windowBits, memLevel, strategy); + ZErrorCode errC; + try + { + errC = ZLibNative.CreateZLibStreamForDeflate(out _zlibStream, zlibCompressionLevel, + windowBits, memLevel, strategy); + } + catch (Exception cause) + { + throw new ZLibException(SR.ZLibErrorDLLLoadError, cause); + } + + switch (errC) + { + case ZErrorCode.Ok: + return; + + case ZErrorCode.MemError: + throw new ZLibException(SR.ZLibErrorNotEnoughMemory, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); + + case ZErrorCode.VersionError: + throw new ZLibException(SR.ZLibErrorVersionMismatch, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); + + case ZErrorCode.StreamError: + throw new ZLibException(SR.ZLibErrorIncorrectInitParameters, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); + + default: + throw new ZLibException(SR.ZLibErrorUnexpected, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); + } } ~Deflater() @@ -198,39 +225,6 @@ namespace System.IO.Compression } } - private void DeflateInit(ZLibNative.CompressionLevel compressionLevel, int windowBits, int memLevel, - ZLibNative.CompressionStrategy strategy) - { - ZErrorCode errC; - try - { - errC = ZLibNative.CreateZLibStreamForDeflate(out _zlibStream, compressionLevel, - windowBits, memLevel, strategy); - } - catch (Exception cause) - { - throw new ZLibException(SR.ZLibErrorDLLLoadError, cause); - } - - switch (errC) - { - case ZErrorCode.Ok: - return; - - case ZErrorCode.MemError: - throw new ZLibException(SR.ZLibErrorNotEnoughMemory, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); - - case ZErrorCode.VersionError: - throw new ZLibException(SR.ZLibErrorVersionMismatch, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); - - case ZErrorCode.StreamError: - throw new ZLibException(SR.ZLibErrorIncorrectInitParameters, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); - - default: - throw new ZLibException(SR.ZLibErrorUnexpected, "deflateInit2_", (int)errC, _zlibStream.GetErrorMessage()); - } - } - private ZErrorCode Deflate(ZFlushCode flushCode) { ZErrorCode errC; diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs index 2c0a2be..78fcd17 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs @@ -19,7 +19,7 @@ namespace System.IO.Compression private bool _finished; // Whether the end of the stream has been reached private bool _isDisposed; // Prevents multiple disposals private readonly int _windowBits; // The WindowBits parameter passed to Inflater construction - private ZLibNative.ZLibStreamHandle _zlibStream; // The handle to the primary underlying zlib stream + private ZLibNative.ZLibStreamHandle _zlibStream = null!; // The handle to the primary underlying zlib stream, initialized by a method that is called from the constructor private GCHandle _inputBufferHandle; // The handle to the buffer that provides input to _zlibStream private readonly long _uncompressedSize; private long _currentInflatedCount; diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibException.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibException.cs index 1ee950b..660a3c4 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibException.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibException.cs @@ -13,8 +13,8 @@ namespace System.IO.Compression [System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ZLibException : IOException, ISerializable { - private readonly string _zlibErrorContext = string.Empty; - private readonly string _zlibErrorMessage = string.Empty; + private readonly string? _zlibErrorContext = string.Empty; + private readonly string? _zlibErrorMessage = string.Empty; private readonly ZLibNative.ErrorCode _zlibErrorCode = ZLibNative.ErrorCode.Ok; /// @@ -25,7 +25,7 @@ namespace System.IO.Compression /// A description of the context within zlib where the error occurred (e.g. the function name). /// The error code returned by a ZLib function that caused this exception. /// The string provided by ZLib as error information (unlocalised). - public ZLibException(string message, string zlibErrorContext, int zlibErrorCode, string zlibErrorMessage) : base(message) + public ZLibException(string? message, string? zlibErrorContext, int zlibErrorCode, string? zlibErrorMessage) : base(message) { _zlibErrorContext = zlibErrorContext; _zlibErrorCode = (ZLibNative.ErrorCode)zlibErrorCode; @@ -46,7 +46,7 @@ namespace System.IO.Compression /// /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null. - public ZLibException(string message, Exception innerException) : base(message, innerException) { } + public ZLibException(string? message, Exception? innerException) : base(message, innerException) { } /// /// Initializes a new ZLibException with serialized data. diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibNative.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibNative.cs index 713f816..99e3ee7 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibNative.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/ZLibNative.cs @@ -312,7 +312,7 @@ namespace System.IO.Compression } // This can work even after XxflateEnd(). - public string GetErrorMessage() => _zStream.msg != ZNullPtr ? Marshal.PtrToStringAnsi(_zStream.msg) : string.Empty; + public string GetErrorMessage() => _zStream.msg != ZNullPtr ? Marshal.PtrToStringAnsi(_zStream.msg)! : string.Empty; } public static ErrorCode CreateZLibStreamForDeflate(out ZLibStreamHandle zLibStreamHandle, CompressionLevel level, diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/GZipStream.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/GZipStream.cs index e938bbd..00134ee 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/GZipStream.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/GZipStream.cs @@ -72,7 +72,7 @@ namespace System.IO.Compression return _deflateStream.ReadByte(); } - public override IAsyncResult BeginRead(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState) => + public override IAsyncResult BeginRead(byte[] array, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) => TaskToApm.Begin(ReadAsync(array, offset, count, CancellationToken.None), asyncCallback, asyncState); public override int EndRead(IAsyncResult asyncResult) => @@ -100,7 +100,7 @@ namespace System.IO.Compression } } - public override IAsyncResult BeginWrite(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState) => + public override IAsyncResult BeginWrite(byte[] array, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) => TaskToApm.Begin(WriteAsync(array, offset, count, CancellationToken.None), asyncCallback, asyncState); public override void EndWrite(IAsyncResult asyncResult) => @@ -142,7 +142,7 @@ namespace System.IO.Compression { _deflateStream.Dispose(); } - _deflateStream = null; + _deflateStream = null!; } finally { @@ -157,17 +157,17 @@ namespace System.IO.Compression return base.DisposeAsync(); } - DeflateStream ds = _deflateStream; + DeflateStream? ds = _deflateStream; if (ds != null) { - _deflateStream = null; + _deflateStream = null!; return ds.DisposeAsync(); } return default; } - public Stream BaseStream => _deflateStream?.BaseStream; + public Stream BaseStream => _deflateStream?.BaseStream!; public override Task ReadAsync(byte[] array, int offset, int count, CancellationToken cancellationToken) { diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/PositionPreservingWriteOnlyStreamWrapper.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/PositionPreservingWriteOnlyStreamWrapper.cs index 6daf909..8ca07e0 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/PositionPreservingWriteOnlyStreamWrapper.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/PositionPreservingWriteOnlyStreamWrapper.cs @@ -36,7 +36,7 @@ namespace System.IO.Compression _stream.Write(buffer, offset, count); } - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object? state) { _position += count; return _stream.BeginWrite(buffer, offset, count, callback, state); diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs index 3d5a22e..a62b274 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs @@ -14,9 +14,9 @@ namespace System.IO.Compression { public class ZipArchive : IDisposable { - private Stream _archiveStream; - private ZipArchiveEntry _archiveStreamOwner; - private BinaryReader _archiveReader; + private readonly Stream _archiveStream; + private ZipArchiveEntry? _archiveStreamOwner; + private BinaryReader? _archiveReader; private ZipArchiveMode _mode; private List _entries; private ReadOnlyCollection _entriesCollection; @@ -27,9 +27,9 @@ namespace System.IO.Compression private bool _isDisposed; private uint _numberOfThisDisk; //only valid after ReadCentralDirectory private long _expectedNumberOfEntries; - private Stream _backingStream; - private byte[] _archiveComment; - private Encoding _entryNameEncoding; + private Stream? _backingStream; + private byte[]? _archiveComment; + private Encoding? _entryNameEncoding; #if DEBUG_FORCE_ZIP64 public bool _forceZip64; @@ -117,13 +117,99 @@ namespace System.IO.Compression /// otherwise an is thrown. /// /// If a Unicode encoding other than UTF-8 is specified for the entryNameEncoding. - public ZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding) + public ZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding? entryNameEncoding) { if (stream == null) throw new ArgumentNullException(nameof(stream)); EntryNameEncoding = entryNameEncoding; - Init(stream, mode, leaveOpen); + Stream? extraTempStream = null; + + try + { + _backingStream = null; + + // check stream against mode + switch (mode) + { + case ZipArchiveMode.Create: + if (!stream.CanWrite) + throw new ArgumentException(SR.CreateModeCapabilities); + break; + case ZipArchiveMode.Read: + if (!stream.CanRead) + throw new ArgumentException(SR.ReadModeCapabilities); + if (!stream.CanSeek) + { + _backingStream = stream; + extraTempStream = stream = new MemoryStream(); + _backingStream.CopyTo(stream); + stream.Seek(0, SeekOrigin.Begin); + } + break; + case ZipArchiveMode.Update: + if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek) + throw new ArgumentException(SR.UpdateModeCapabilities); + break; + default: + // still have to throw this, because stream constructor doesn't do mode argument checks + throw new ArgumentOutOfRangeException(nameof(mode)); + } + + _mode = mode; + if (mode == ZipArchiveMode.Create && !stream.CanSeek) + _archiveStream = new PositionPreservingWriteOnlyStreamWrapper(stream); + else + _archiveStream = stream; + _archiveStreamOwner = null; + if (mode == ZipArchiveMode.Create) + _archiveReader = null; + else + _archiveReader = new BinaryReader(_archiveStream); + _entries = new List(); + _entriesCollection = new ReadOnlyCollection(_entries); + _entriesDictionary = new Dictionary(); + _readEntries = false; + _leaveOpen = leaveOpen; + _centralDirectoryStart = 0; // invalid until ReadCentralDirectory + _isDisposed = false; + _numberOfThisDisk = 0; // invalid until ReadCentralDirectory + _archiveComment = null; + + switch (mode) + { + case ZipArchiveMode.Create: + _readEntries = true; + break; + case ZipArchiveMode.Read: + ReadEndOfCentralDirectory(); + break; + case ZipArchiveMode.Update: + default: + Debug.Assert(mode == ZipArchiveMode.Update); + if (_archiveStream.Length == 0) + { + _readEntries = true; + } + else + { + ReadEndOfCentralDirectory(); + EnsureCentralDirectoryRead(); + foreach (ZipArchiveEntry entry in _entries) + { + entry.ThrowIfNotOpenable(needToUncompress: false, needToLoadIntoMemory: true); + } + } + break; + } + } + catch + { + if (extraTempStream != null) + extraTempStream.Dispose(); + + throw; + } } /// @@ -241,7 +327,7 @@ namespace System.IO.Compression /// The Zip archive is corrupt and the entries cannot be retrieved. /// A path relative to the root of the archive, identifying the desired entry. /// A wrapper for the file entry in the archive. If no entry in the archive exists with the specified name, null will be returned. - public ZipArchiveEntry GetEntry(string entryName) + public ZipArchiveEntry? GetEntry(string entryName) { if (entryName == null) throw new ArgumentNullException(nameof(entryName)); @@ -250,18 +336,17 @@ namespace System.IO.Compression throw new NotSupportedException(SR.EntriesInCreateMode); EnsureCentralDirectoryRead(); - ZipArchiveEntry result; - _entriesDictionary.TryGetValue(entryName, out result); + _entriesDictionary.TryGetValue(entryName, out ZipArchiveEntry? result); return result; } - internal BinaryReader ArchiveReader => _archiveReader; + internal BinaryReader? ArchiveReader => _archiveReader; internal Stream ArchiveStream => _archiveStream; internal uint NumberOfThisDisk => _numberOfThisDisk; - internal Encoding EntryNameEncoding + internal Encoding? EntryNameEncoding { get { return _entryNameEncoding; } @@ -402,97 +487,6 @@ namespace System.IO.Compression } } - private void Init(Stream stream, ZipArchiveMode mode, bool leaveOpen) - { - Stream extraTempStream = null; - - try - { - _backingStream = null; - - // check stream against mode - switch (mode) - { - case ZipArchiveMode.Create: - if (!stream.CanWrite) - throw new ArgumentException(SR.CreateModeCapabilities); - break; - case ZipArchiveMode.Read: - if (!stream.CanRead) - throw new ArgumentException(SR.ReadModeCapabilities); - if (!stream.CanSeek) - { - _backingStream = stream; - extraTempStream = stream = new MemoryStream(); - _backingStream.CopyTo(stream); - stream.Seek(0, SeekOrigin.Begin); - } - break; - case ZipArchiveMode.Update: - if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek) - throw new ArgumentException(SR.UpdateModeCapabilities); - break; - default: - // still have to throw this, because stream constructor doesn't do mode argument checks - throw new ArgumentOutOfRangeException(nameof(mode)); - } - - _mode = mode; - if (mode == ZipArchiveMode.Create && !stream.CanSeek) - _archiveStream = new PositionPreservingWriteOnlyStreamWrapper(stream); - else - _archiveStream = stream; - _archiveStreamOwner = null; - if (mode == ZipArchiveMode.Create) - _archiveReader = null; - else - _archiveReader = new BinaryReader(_archiveStream); - _entries = new List(); - _entriesCollection = new ReadOnlyCollection(_entries); - _entriesDictionary = new Dictionary(); - _readEntries = false; - _leaveOpen = leaveOpen; - _centralDirectoryStart = 0; // invalid until ReadCentralDirectory - _isDisposed = false; - _numberOfThisDisk = 0; // invalid until ReadCentralDirectory - _archiveComment = null; - - switch (mode) - { - case ZipArchiveMode.Create: - _readEntries = true; - break; - case ZipArchiveMode.Read: - ReadEndOfCentralDirectory(); - break; - case ZipArchiveMode.Update: - default: - Debug.Assert(mode == ZipArchiveMode.Update); - if (_archiveStream.Length == 0) - { - _readEntries = true; - } - else - { - ReadEndOfCentralDirectory(); - EnsureCentralDirectoryRead(); - foreach (ZipArchiveEntry entry in _entries) - { - entry.ThrowIfNotOpenable(needToUncompress: false, needToLoadIntoMemory: true); - } - } - break; - } - } - catch - { - if (extraTempStream != null) - extraTempStream.Dispose(); - - throw; - } - } - private void ReadCentralDirectory() { try @@ -503,6 +497,7 @@ namespace System.IO.Compression long numberOfEntries = 0; + Debug.Assert(_archiveReader != null); //read the central directory ZipCentralDirectoryFileHeader currentHeader; bool saveExtraFieldsAndComments = Mode == ZipArchiveMode.Update; @@ -537,6 +532,7 @@ namespace System.IO.Compression long eocdStart = _archiveStream.Position; + Debug.Assert(_archiveReader != null); // read the EOCD ZipEndOfCentralDirectoryBlock eocd; bool eocdProper = ZipEndOfCentralDirectoryBlock.TryReadBlock(_archiveReader, out eocd); diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs index cefa7ab..122a98f 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs @@ -31,18 +31,18 @@ namespace System.IO.Compression private long? _storedOffsetOfCompressedData; private uint _crc32; // An array of buffers, each a maximum of MaxSingleBufferSize in size - private byte[][] _compressedBytes; - private MemoryStream _storedUncompressedData; + private byte[][]? _compressedBytes; + private MemoryStream? _storedUncompressedData; private bool _currentlyOpenForWrite; private bool _everOpenedForWrite; - private Stream _outstandingWriteStream; + private Stream? _outstandingWriteStream; private uint _externalFileAttr; - private string _storedEntryName; - private byte[] _storedEntryNameBytes; + private string _storedEntryName = null!; // indirectly set in constructor using FullName property + private byte[] _storedEntryNameBytes = null!; // only apply to update mode - private List _cdUnknownExtraFields; - private List _lhUnknownExtraFields; - private readonly byte[] _fileComment; + private List? _cdUnknownExtraFields; + private List? _lhUnknownExtraFields; + private readonly byte[]? _fileComment; private readonly CompressionLevel? _compressionLevel; // Initializes, attaches it to archive @@ -274,7 +274,7 @@ namespace System.IO.Compression _archive.ThrowIfDisposed(); _archive.RemoveEntry(this); - _archive = null; + _archive = null!; UnloadStreams(); } @@ -324,6 +324,7 @@ namespace System.IO.Compression { if (_storedOffsetOfCompressedData == null) { + Debug.Assert(_archive.ArchiveReader != null); _archive.ArchiveStream.Seek(_offsetOfLocalHeader, SeekOrigin.Begin); // by calling this, we are using local header _storedEntryNameBytes.Length and extraFieldLength // to find start of data, but still using central directory size information @@ -553,15 +554,15 @@ namespace System.IO.Compression // can throw InvalidDataException internal bool LoadLocalHeaderExtraFieldAndCompressedBytesIfNeeded() { - string message; // we should have made this exact call in _archive.Init through ThrowIfOpenable - Debug.Assert(IsOpenable(false, true, out message)); + Debug.Assert(IsOpenable(false, true, out string? message)); // load local header's extra fields. it will be null if we couldn't read for some reason if (_originallyInArchive) { _archive.ArchiveStream.Seek(_offsetOfLocalHeader, SeekOrigin.Begin); + Debug.Assert(_archive.ArchiveReader != null); _lhUnknownExtraFields = ZipLocalFileHeader.GetExtraFields(_archive.ArchiveReader); } @@ -590,12 +591,11 @@ namespace System.IO.Compression internal void ThrowIfNotOpenable(bool needToUncompress, bool needToLoadIntoMemory) { - string message; - if (!IsOpenable(needToUncompress, needToLoadIntoMemory, out message)) + if (!IsOpenable(needToUncompress, needToLoadIntoMemory, out string? message)) throw new InvalidDataException(message); } - private CheckSumAndSizeWriteStream GetDataCompressor(Stream backingStream, bool leaveBackingStreamOpen, EventHandler onClose) + private CheckSumAndSizeWriteStream GetDataCompressor(Stream backingStream, bool leaveBackingStreamOpen, EventHandler? onClose) { // stream stack: backingStream -> DeflateStream -> CheckSumWriteStream @@ -627,7 +627,7 @@ namespace System.IO.Compression leaveCompressorStreamOpenOnClose, this, onClose, - (long initialPosition, long currentPosition, uint checkSum, Stream backing, ZipArchiveEntry thisRef, EventHandler closeHandler) => + (long initialPosition, long currentPosition, uint checkSum, Stream backing, ZipArchiveEntry thisRef, EventHandler? closeHandler) => { thisRef._crc32 = checkSum; thisRef._uncompressedSize = currentPosition; @@ -640,7 +640,7 @@ namespace System.IO.Compression private Stream GetDataDecompressor(Stream compressedStreamToRead) { - Stream uncompressedStream = null; + Stream? uncompressedStream = null; switch (CompressionMethod) { case CompressionMethodValues.Deflate: @@ -680,10 +680,10 @@ namespace System.IO.Compression _archive.DebugAssertIsStillArchiveStreamOwner(this); _everOpenedForWrite = true; - CheckSumAndSizeWriteStream crcSizeStream = GetDataCompressor(_archive.ArchiveStream, true, (object o, EventArgs e) => + CheckSumAndSizeWriteStream crcSizeStream = GetDataCompressor(_archive.ArchiveStream, true, (object? o, EventArgs e) => { // release the archive stream - var entry = (ZipArchiveEntry)o; + var entry = (ZipArchiveEntry)o!; entry._archive.ReleaseArchiveStream(entry); entry._outstandingWriteStream = null; }); @@ -709,11 +709,11 @@ namespace System.IO.Compression // so we don't fill in any size information // those fields get figured out when we call GetCompressor as we write it to // the actual archive - thisRef._currentlyOpenForWrite = false; + thisRef!._currentlyOpenForWrite = false; }); } - private bool IsOpenable(bool needToUncompress, bool needToLoadIntoMemory, out string message) + private bool IsOpenable(bool needToUncompress, bool needToLoadIntoMemory, out string? message) { message = null; @@ -748,6 +748,7 @@ namespace System.IO.Compression message = SR.LocalFileHeaderCorrupt; return false; } + Debug.Assert(_archive.ArchiveReader != null); _archive.ArchiveStream.Seek(_offsetOfLocalHeader, SeekOrigin.Begin); if (needToUncompress && !needToLoadIntoMemory) { @@ -932,6 +933,7 @@ namespace System.IO.Compression // according to ZIP specs, zero-byte files MUST NOT include file data if (_uncompressedSize != 0) { + Debug.Assert(_compressedBytes != null); foreach (byte[] compressedBytes in _compressedBytes) { _archive.ArchiveStream.Write(compressedBytes, 0, compressedBytes.Length); diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs index 9f40670..bad189c 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs @@ -185,7 +185,7 @@ namespace System.IO.Compression return false; // this pattern needed because nested using blocks trigger CA2202 - MemoryStream ms = null; + MemoryStream? ms = null; try { ms = new MemoryStream(extraField.Data); @@ -555,8 +555,8 @@ namespace System.IO.Compression public long RelativeOffsetOfLocalHeader; public byte[] Filename; - public byte[] FileComment; - public List ExtraFields; + public byte[]? FileComment; + public List? ExtraFields; // if saveExtraFieldsAndComments is false, FileComment and ExtraFields will be null // in either case, the zip64 extra field info will be incorporated into other fields @@ -653,7 +653,7 @@ namespace System.IO.Compression public uint OffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber; public byte[] ArchiveComment; - public static void WriteBlock(Stream stream, long numberOfEntries, long startOfCentralDirectory, long sizeOfCentralDirectory, byte[] archiveComment) + public static void WriteBlock(Stream stream, long numberOfEntries, long startOfCentralDirectory, long sizeOfCentralDirectory, byte[]? archiveComment) { BinaryWriter writer = new BinaryWriter(stream); diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs index 129f787..17d3b25 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs @@ -12,16 +12,16 @@ namespace System.IO.Compression private readonly bool _closeBaseStream; // Delegate that will be invoked on stream disposing - private readonly Action _onClosed; + private readonly Action? _onClosed; // Instance that will be passed to _onClose delegate - private readonly ZipArchiveEntry _zipArchiveEntry; + private readonly ZipArchiveEntry? _zipArchiveEntry; private bool _isDisposed; internal WrappedStream(Stream baseStream, bool closeBaseStream) : this(baseStream, closeBaseStream, null, null) { } - private WrappedStream(Stream baseStream, bool closeBaseStream, ZipArchiveEntry entry, Action onClosed) + private WrappedStream(Stream baseStream, bool closeBaseStream, ZipArchiveEntry? entry, Action? onClosed) { _baseStream = baseStream; _closeBaseStream = closeBaseStream; @@ -30,7 +30,7 @@ namespace System.IO.Compression _isDisposed = false; } - internal WrappedStream(Stream baseStream, ZipArchiveEntry entry, Action onClosed) + internal WrappedStream(Stream baseStream, ZipArchiveEntry entry, Action? onClosed) : this(baseStream, false, entry, onClosed) { } public override long Length @@ -282,10 +282,10 @@ namespace System.IO.Compression // this is the position in BaseBaseStream private long _initialPosition; private readonly ZipArchiveEntry _zipArchiveEntry; - private readonly EventHandler _onClose; + private readonly EventHandler? _onClose; // Called when the stream is closed. // parameters are initialPosition, currentPosition, checkSum, baseBaseStream, zipArchiveEntry and onClose handler - private readonly Action _saveCrcAndSizes; + private readonly Action _saveCrcAndSizes; // parameters to saveCrcAndSizes are // initialPosition (initialPosition in baseBaseStream), @@ -295,8 +295,8 @@ namespace System.IO.Compression // zipArchiveEntry passed here so as to avoid closure allocation, // onClose handler passed here so as to avoid closure allocation public CheckSumAndSizeWriteStream(Stream baseStream, Stream baseBaseStream, bool leaveOpenOnClose, - ZipArchiveEntry entry, EventHandler onClose, - Action saveCrcAndSizes) + ZipArchiveEntry entry, EventHandler? onClose, + Action saveCrcAndSizes) { _baseStream = baseStream; _baseBaseStream = baseBaseStream;