-
Notifications
You must be signed in to change notification settings - Fork 484
Avoid reading unused bytes from PNG streams #535
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
Changes from 1 commit
b28f43f
e116370
c588b95
6247ec7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,7 +86,7 @@ public Iterable<PngChunk> extract(@NotNull final SequentialReader reader, @Nulla | |
// Process the next chunk. | ||
int chunkDataLength = reader.getInt32(); | ||
|
||
if (chunkDataLength < 0) | ||
if ((chunkDataLength < 0) || (chunkDataLength > reader.available())) | ||
throw new PngProcessingException("PNG chunk length exceeds maximum"); | ||
|
||
PngChunkType chunkType = new PngChunkType(reader.getBytes(4)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For some reason I'm sure makes a lot of sense to GitHub, I can't place a comment any further down than here. I wanted to comment on line 96 below though. I'm not saying that this will solve it, but I see one possibility to at least make this less likely to happen. As far as I can tell, byte[] chunkData;
if (willStoreChunk) {
chunkData = reader.getBytes(chunkDataLength);
} else {
chunkData = null // To satisfy the compiler
reader.skip(chunkDataLength)
} With that in place, I guess some sane maximum sizes could be deducted based on the chunk type. I'm no PNG expert, but I would assume that only the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, this would be a nice workaround! In case of this specific file, the problematic chunk is not read, only skipped. So in the end I can see minor complication in the fact that On the other hand, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've implemented the changes you proposed, added a short comment regarding the chunk data reading and also included the corrupted file in the tests. Let me know if this solution is OK with you. Thanks! |
||
|
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.
I'm afraid that this isn't a valid use of
available()
. Here's the JavaDoc for the method:This is a more fundamental "problem", the nature of a stream is that the total size might be unknown. For
SequentialByteArrayReader
usingavailable()
would yield the correct results, while forStreamReader
(and potentially other implementations` it would not.I don't know how a "sane maximum value" could be deducted, but I guess some more finesse is needed.
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.
OK, you are right about this. There are implementations of
InputStream
which might return unexpected results foravailable()
. I didn't realized that when I implemented my fix. I just thoughtavailable()
is the best chance there is for estimating stream size. And only thought about metadata-extractor as a tool for bounded streams.What do you suggest then? Using
available()
might fail for some crazy streams. And technically there is nothing wrong with allocating array up to max Integer. It can cause some Exceptions which are impossible to catch/prevent from happening outside of the library.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.
I'm not sure I have a suggestion from the top of my head. I guess a check could be made with
instanceof
and then use your logic if the reader is aSequentialByteArrayReader
, but this still leaves the question of what to do with all the other cases.Regarding
available()
, it's not just "crazy streams" where this fails. Generally, forFileInputStream
it returns the remaining bytes of the file, and I think that's the reason why many seem to think it reports "the remainder of the stream". For network streams for example,available()
will generally just report the remainder of bytes in the buffer at that time, which will probably be a relatively small 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.
It is true that this might be unnecessary optimization as allocating large buffer is generally OK and reading more bytes from a stream than it actually contains should result in
java.io.EOFException: End of data reached.
Let me know though if you come up with any solution or a trick how to handle this issue. I realize it is not caused by the library, but such threat of OOM is really undesirable one.