-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Replace ZipArchive calls of stream.Read with stream.ReadExactly or stream.ReadAtLeast #114026
Comments
Tagging subscribers to this area: @dotnet/area-system-io-compression |
@edwardneal A fix for this would have to be worked on top of #114023 By using the test and custom stream shared in the description, these would be some of the places that would cause problems: runtime/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs Line 694 in 3e22ac1
runtime/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs Line 817 in 3e22ac1
runtime/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs Line 523 in 3e22ac1
What's good about the ReadAtLeast and ReadExactly methods, is that if we have places using Read that try to confirm we received the expected number of bytes, we can simplify the code considerably, as those two new stream methods will take care of reading reliably for us. |
Thanks @carlossanlop - I can see that 114023 was merged earlier, and I'll pick this up. |
Appreciate it! Let me know if you need any help with it. |
There are various places in System.IO.Compression.ZipArchive* that are currently calling
stream.Read
and assuming the number of bytes returned will be the requested one. This method does not work like that, it can return less than the requested number of bytes.This is a problem when using a stream whose Read method constantly returns less than the requested number of bytes. I tested the extreme scenario of creating my own custom Stream implementation, overriding the Read methods and forcing them to always return one byte at a time. This causes valid archives to throw unexpected exceptions when calling archive.Entries, as EnsureCentralDirectoryRead will be unable to finish reading all the entry bytes because many places assume that the number of bytes returned is insufficient and exit early.
The fix is to replace these Read calls with ReadExactly or ReadAtLeast, depending on each case (the former always throws if not enough bytes, the latter can optionally not throw on end of stream).
@edwardneal would you be interested in looking into this?
Here's my custom stream implementation:
Expand
And here is a test with a valid zip that throws:
Expand
The text was updated successfully, but these errors were encountered: