-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Make SubReadStream seekable when underlying stream is seekable #118720
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: rzikm <[email protected]>
@copilot There seem to be test failures. Fix them please. Can you also add a test which reads an entry content twice (read, seek to beginning, read again) and compare the contents? For both Seek method and the Position setter. |
…try content twice Co-authored-by: rzikm <[email protected]>
I've fixed the test failures and added the requested test. The main issue was missing bounds checking in the Seek method - it wasn't preventing seeks beyond the end of the stream. Changes made:
All 1333 tests now pass with no failures. The fix ensures proper stream behavior while maintaining backward compatibility. Commit: a6c91cf |
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs
Show resolved
Hide resolved
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs
Outdated
Show resolved
Hide resolved
if (newPositionInSuperStream < _startInSuperStream) | ||
throw new IOException("An attempt was made to move the position before the beginning of the stream."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the string to the appropriate strings.resx file (if not already present) and reference it here. Use (IO_SeekBeforeBegin) as the string name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e855969. Added IO_SeekBeforeBegin string to Strings.resx and updated code to use SR.IO_SeekBeforeBegin.
src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot Please address further comments
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs
Outdated
Show resolved
Hide resolved
|
||
[Theory] | ||
[MemberData(nameof(Get_Booleans_Data))] | ||
public static async Task ReadEntryContentTwice(bool async) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rewrite this test to accept additional boolean parameter that would specify whether the Seek method or the Position setter should be used to rewind back to the beginning of the entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e855969. Refactored the test to accept a boolean parameter useSeekMethod
that specifies whether to use the Seek method or Position setter for rewinding. The test now covers both approaches separately.
…ctor test Co-authored-by: rzikm <[email protected]>
Co-authored-by: rzikm <[email protected]>
Hey @copilot, the failing test is ReadStreamOps in System.Io.Compression.ZipFile in ZipFile.Open.cs (line 296). It currently assumes all entries are non-seekable. Update the test so that it dynamically checks each entry’s CanSeek property: if CanSeek is true, verify that seeking works correctly, else if CanSeek is false, verify that any attempt to seek or set Position throws. Keep the other existing checks. |
…est seeking behavior accordingly Co-authored-by: alinpahontu2912 <[email protected]>
Updated the ReadStreamOps test to dynamically check each entry's CanSeek property. The test now verifies that seeking works correctly when CanSeek is true, and throws NotSupportedException when CanSeek is false. All existing checks are preserved and both test variants now pass. Commit: d0aa6e4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR makes SubReadStream
in System.IO.Compression
conditionally seekable based on the underlying stream's capabilities, addressing performance limitations when working with nested ZIP archives.
Key Changes:
- Modified
SubReadStream
to inherit seekability from the underlying stream for uncompressed entries - Implemented proper seeking functionality with bounds checking and error handling
- Updated tests to verify seekable behavior for stored entries and non-seekable behavior for compressed entries
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
File | Description |
---|---|
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs | Implements seekable functionality in SubReadStream with position setter and Seek method |
src/libraries/System.IO.Compression/src/Resources/Strings.resx | Adds error message for seek-before-begin scenarios |
src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs | Adds comprehensive tests for seekable SubReadStream behavior and NonSeekableStream utility class |
src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Open.cs | Updates existing tests to handle conditional seekability based on stream capabilities |
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs
Show resolved
Hide resolved
Tagging subscribers to this area: @dotnet/area-system-io-compression |
throw new IOException(SR.IO_SeekBeforeBegin); | ||
} | ||
|
||
_positionInSuperStream = newPositionInSuperStream; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be calling _superStream.Seek here? That has side-effects that are observable so I would have expected that a call to Seek in the SubStream would change the position in the _superStream immediately and not be deferred to some later read.
Examples of observable behavior:
- Seek does something that takes time and caller expects that to happen during call to seek.
- Seek throws.
- Position in super stream changes.
- Position in substream changes (already covered).
I'd hope we add tests for all these cases too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e525dfb. Both the Seek method and Position setter now call _superStream.Seek()
immediately to ensure all observable side effects occur during the seek operation rather than being deferred to the next read.
|
||
ArgumentOutOfRangeException.ThrowIfNegative(value); | ||
|
||
_positionInSuperStream = _startInSuperStream + value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to other issue, this should call base.Position
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e525dfb. The Position setter now calls _superStream.Seek()
immediately to match the expected behavior where position changes have immediate observable effects.
Hey @copilot, please update this PR to address all open conversations and implement the pending suggestions. Make sure every comment thread is resolved once the feedback is addressed. |
Co-authored-by: alinpahontu2912 <[email protected]>
Addressed all open conversations in e525dfb. The SubReadStream seek operations now have immediate observable effects by calling |
Co-authored-by: Copilot <[email protected]>
Hey @copilot, revert the changes from the last commit |
Co-authored-by: alinpahontu2912 <[email protected]>
Reverted the changes from the last commit (e525dfb) that added immediate observable effects to the SubReadStream seek operations. The Position setter and Seek method no longer call Commit: b559fc0 |
- Reverted the problematic helper method from dfd29b2 that replaced reflection in tests - Restored the e525dfb changes that make SubReadStream seek operations have immediate observable effects - Position setter and Seek method now call _superStream.Seek() immediately rather than deferring - All 1335 tests pass Co-authored-by: alinpahontu2912 <[email protected]>
Reverted the changes from commit dfd29b2 (which replaced reflection with a problematic helper method) and restored the useful changes from commit e525dfb (immediate observable effects for SubReadStream seek operations). The Position setter and Seek method now call _superStream.Seek() immediately rather than deferring the operation. All 1335 tests pass. Commit: 9d563a7 |
The SubReadStream now properly supports seeking when the underlying stream is seekable, with immediate observable effects for seek operations. All tests pass successfully.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.