Fix reading EXR images on 32bit Windows with OpenEXR 3.3 #1952
+1
−1
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR fixes an issue with
atomic_compare_exchange_strong
in chunk.c due to inappropriate type on 32 bit platforms.Context:
When switching from OpenEXR 3.2.4 to OpenEXR 3.3.2, I noticed that reading image content from file (via
ImfInputFile::readPixels(int, int)
) failed most of the time (but not always) in 32 bit Windows.I found that OpenEXR 3.3 apparently changed the reading routine to use
extract_chunk_table
from OpenEXRCore's chunk.c.Here, two variables
eptr
andnptr
are declared to be of typeuintptr_t
inopenexr/src/lib/OpenEXRCore/chunk.c
Line 568 in 8bc3fae
However, in
openexr/src/lib/OpenEXRCore/chunk.c
Lines 644 to 647 in 8bc3fae
, they are used in an
atomic_compare_exchange_strong
call asuint64_t*
anduint64_t
respectively.See
openexr/src/lib/OpenEXRCore/chunk.c
Lines 38 to 47 in 8bc3fae
While the latter isn't a problem per-se, the usage of
&eptr
asuint64_t*
letsatomic_compare_exchange_strong
interpret whatever is at the address ofeptr
as an 8 byte long number.However, the actual type
uintptr_t
is only 4 bytes long.So, whatever is in the next four bytes will garble the value originally stored in
eptr
.As a result in the comparison of
prev
(which holds "0" if the exchange worked as expected) does not compare to the expected and declare value ofuintptr_t eptr = 0
from line 568 but any number that is in the respective full 8 bytes of memory will fail and set the full 8 bytes to 0.openexr/src/lib/OpenEXRCore/chunk.c
Lines 44 to 46 in 8bc3fae
This not only misleads the calling code to assume that it failed to thread-safe exchange the pointers but also overwrites the
ctable
pointer with the (now 8 bytes of zeros) addresss and eventually (falsely) report "out of memory".openexr/src/lib/OpenEXRCore/chunk.c
Lines 649 to 652 in 8bc3fae
My proposed minimal fix simply changes the type of
eptr
(andnptr
) to always be an unsigned 64 bit value, which should work for both, 32 and 64 bit platforms.