-
-
Notifications
You must be signed in to change notification settings - Fork 851
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
Png- Do not attempt to read data for chunks of length 0. #2561
Conversation
@@ -1569,6 +1570,11 @@ private void SkipChunkDataAndCrc(in PngChunk chunk) | |||
[MethodImpl(InliningOptions.ShortMethod)] | |||
private IMemoryOwner<byte> ReadChunkData(int length) | |||
{ | |||
if (length == 0) |
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.
We avoid the read here because Png still has to do a CRC check which if does not occur leads to failure during reading of chained Png images within a single 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.
The behavior with these changes is still odd: we run through the stream with ~500 attempts to read a 0-byte chunk. It doesn't look like the correct/optimal thing to do for such an input.
This code doesn't look correct to me:
ImageSharp/src/ImageSharp/Formats/Png/PngDecoderCore.cs
Lines 1470 to 1479 in d93bc6c
while (length < 0 || length > (this.currentStream.Length - this.currentStream.Position)) | |
{ | |
// Not a valid chunk so try again until we reach a known chunk. | |
if (!this.TryReadChunkLength(buffer, out length)) | |
{ | |
chunk = default; | |
return false; | |
} | |
} |
If length > (this.currentStream.Length - this.currentStream.Position)
because the file is truncated, we just start interpreting the following (type/data) bytes as length until length
becomes 0. If we really don't want to throw/abort here, why not to process the chunk in the truncated form instead?
Edit: I guess there was some corrupt input this was logic was introduced for but is this really the best we can do?
Is it the best we can do? We differ from libpng here. We continue reading after parsing a length greater than 2147483647 while libpng will throw. libpng doesn't seem to do the inner check. However, it seems to freely loop like we do. I'm not sure there's a better way to detect chunks while skipping corrupted sections. |
I recked our suite of tests while disabling that section and we only had the one failing image. I don't think we'll hit that path often at all and it's the only way I think that we can be skip bad sections. |
Prerequisites
Description
Png was attempting to read chunk data for chunks of length
0
, for exampleEOF
. This lead, to multiple attempts to read past the end of a stream.