-
Notifications
You must be signed in to change notification settings - Fork 207
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
Remove check that the meta box is zero when searching for a tmap. #2431
base: main
Are you sure you want to change the base?
Conversation
Whether the meta box has size zero or not, it's read in one go. So if the meta box has been seen, all of it has been seen. The only case where it could be read partially is if the provided sizeHint value is too small, but then the parsing code still assumes it has read the whole box. If the whole box is not available yet, the reading function is supposed to return AVIF_RESULT_WAITING_ON_IO.
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.
So if the meta box has been seen, all of it has been seen.
Not sure I follow. One cannot be sure when all of meta
was parsed and in all cases.
Consider the following image with alpha:
- ftyp
- meta size 0
- hdlr
- pitm
- iloc
- iinf
- infe
- infe
- iprp
- ipco
- colr
- auxC
- etc
- ipma
- ipco
- idat
- iref
- auxl
(I have not checked all specifications to ensure this is compliant so I assume it is.)
If one received everything till the iref
box exclusive, it could be considered a valid opaque image. In my opinion this is dangerous because the displayed pixels depend on the file being partially received. It should return TRUNCATED_DATA
instead in my opinion.
Could the same pattern happen for tmap
, for example a missing altr
group at the end or something?
Another inconvenient situation would be some non-compliant duplicated box such as two pitm
or something, where the file is valid as long as truncated just before that invalid box at the end. But this goes into a bigger question of whether custom metadata can be arbitrarily appended at the end of any file of whatever format.
In practice I do not think there is any writer out there using meta
with size 0 and idat
, so it matters little.
If the whole box is not available yet, the reading function is supposed to return
AVIF_RESULT_WAITING_ON_IO
.
Which "reading function"? How can it know that?
@@ -4292,10 +4287,8 @@ static avifResult avifParse(avifDecoder * decoder) | |||
} | |||
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP) | |||
if (needsTmap && !tmapSeen) { | |||
return metaIsSizeZero ? AVIF_RESULT_TRUNCATED_DATA : AVIF_RESULT_BMFF_PARSE_FAILED; |
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 do not why that check was only present for tmap
in the first place.
If the box has size zero, we read until the end of the file in one go, or until Lines 4166 to 4173 in 8aab77e
So the reading function is supposed to return all data until the end of the file, or |
According to the documentation of Lines 1057 to 1067 in 8aab77e
|
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.
So the reading function is supposed to return all data until the end of the file, or
AVIF_RESULT_TRUNCATED_DATA
if not available (in which case we abort directly).
or AVIF_RESULT_WAITING_ON_IO
but this is also returned immediately.
This does mean that you can't do any sort of incremental or progressive decoding if you're using idat right now.
I am not so sure, because avifParse()
may stop before trying to read the whole meta
box.
Consider:
- A file that is compliant when truncated at N bytes
avifParse()
given these N bytes- With
sawEverythingNeeded = !needsTmap || tmapSeen
, it will try to read more, leaving the choice to returnTRUNCATED_DATA
orWAITING_ON_IO
toavifIOReadFunc
. - Without
sawEverythingNeeded = !needsTmap || tmapSeen
, it will maybe returnOK
-> this may lead to different pixels depending on parsing the whole file or not.
So for this part of the PR I am not so sure.
For the metaIsSizeZero
part:
metaIsSizeZero
is looked up only when avifIOReadFunc
returned OK
, meaning the full size was read. And metaIsSizeZero
is necessary to differentiate between a non-compliant file that may become valid with more bytes (TRUNCATED
), or a non-compliant file that is faulty no matter what bytes are appended (PARSE_FAILED
).
Sorry yes I meant it will return AVIF_RESULT_WAITING_ON_IO, not AVIF_RESULT_TRUNCATED_DATA. I don't think avifIOReadFunc is supposed to return AVIF_RESULT_TRUNCATED_DATA given that description. We can discuss this more in person on Monday. |
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.
As discussed offline, looks good to me.
A few comments about what we discussed, more comments for future reference:
The last point might be the most controversial. Previously it seems we were trying to return AVIF_RESULT_TRUNCATED_DATA in this case. But currently the AVIF_RESULT_TRUNCATED_DATA return status is not documented so there are no guarantees on when it is returned, so it should be ok to change. |
Knowing the data is truncated can be useful when a file is partially downloaded and a browser tries to figure out some information about the image (and first, make sure it is valid). |
I guess we can keep the check but I'm not sure we do this very consistently currently. We would need to add a test. |
(Actually this code applies only in the super rare case where the meta box is size '0' AND the file happens to be truncated just at the boundary between two subboxes of the meta box) |
Unless I'm misunderstanding something, whether the meta box has size zero or not, it's read in one go. So if the meta box has been seen, all of it has been seen. The only case where it could be read partially is if the provided sizeHint value is too small, but then the parsing code still assumes it has read the whole box.
If the whole box is not available yet, the reading function is supposed to return AVIF_RESULT_WAITING_ON_IO.