GHSA-xc77-xm9h-qxm4 on CTRL-OS 26.05
Aliases: GHSA-xc77-xm9h-qxm4
Packages: openexr
Status: Plausible
Advisory Information
Summary
A malformed deep tiled EXR with a positive
65537 x 65537dataWindow can make the shippedexrmetricstool corrupt heap memory on ILP32 builds.initAndReadDeepTiled()computesnumPixelsas 64-bit but passes it tostd::vector<int>::resize(size_type)for the deep tiled sample-count table, which truncates on 32-bit builds. Fresh validation also reproduced the same behavior on current main.Details
The truncated
sampleCountvector is registered as the sample-count slice.DeepTiledInputPart::readPixelSampleCounts()then copies tile sample-count data for the declared image into that undersized vector, producing an out-of-bounds heap write.This PoC uses only a crafted EXR file through the shipped command-line tool.
PoC
From
/home/br0nzu/openexr/v3.4.13:./report/71.\ OpenEXR\ v3.4.13\ exrmetrics\ ILP32\ deep\ tiled\ sampleCount\ heap\ buffer\ overflow/reproduce.shPoC input:
poc_materials/exrmetrics_deep_tiled_w65537_h65537_tw65537_th4.exrValidation evidence
v3.4.13: original rc=139, ASAN rc=134, UBSAN rc=134. current-main: original rc=139, ASAN rc=134, UBSAN rc=134.
Current-main and patch-overlap logs are saved under
logs/fresh_current_main_ilp32_*andvalidation_summary.txtin this directory.Original crash stderr:
timeout: the monitored command dumped coreFull ASAN output
================================================================= ==2995361==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf72fe804 at pc 0x566c5f42 bp 0xffdb9068 sp 0xffdb8c40 WRITE of size 262148 at 0xf72fe804 thread T0 #0 0x566c5f41 in __asan_memcpy (/home/br0nzu/openexr/v3.4.13/report/71. OpenEXR v3.4.13 exrmetrics ILP32 deep tiled sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0x145f41) (BuildId: 6bc8ac4c4e2527ef7300f003242cf56d2d5d03eb) #1 0x56831b0e in Imf_3_4::(anonymous namespace)::TileProcess::copy_sample_count(Imf_3_4::DeepFrameBuffer const*, int, int, int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:1238:13 #2 0x56831b0e in Imf_3_4::(anonymous namespace)::TileProcess::run_decode(_priv_exr_context_t const*, int, Imf_3_4::DeepFrameBuffer const*, std::vector<Imf_3_4::DeepSlice, std::allocator<Imf_3_4::DeepSlice>> const&) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:1072:5 #3 0x56829aec in Imf_3_4::DeepTiledInputFile::Data::readTiles(int, int, int, int, int, int, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:968:20 #4 0x5682e6ac in Imf_3_4::DeepTiledInputFile::readPixelSampleCounts(int, int, int, int, int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:690:16 #5 0x567477bf in Imf_3_4::DeepTiledInputPart::readPixelSampleCounts(int, int, int, int, int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputPart.cpp:200:11 #6 0x56726f86 in initAndReadDeepTiled(std::vector<int, std::allocator<int>>&, std::vector<std::vector<char, std::allocator<char>>, std::allocator<std::vector<char, std::allocator<char>>>>&, std::vector<std::vector<char*, std::allocator<char*>>, std::allocator<std::vector<char*, std::allocator<char*>>>>&, Imf_3_4::DeepFrameBuffer&, Imf_3_4::DeepTiledInputPart&, std::vector<int, std::allocator<int>> const*, Imf_3_4::Header const&, std::vector<double, std::allocator<double>>&, std::vector<double, std::allocator<double>>&) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:533:12 #7 0x567297e9 in initAndReadFile(Imf_3_4::MultiPartInputFile&, std::vector<Imf_3_4::Header, std::allocator<Imf_3_4::Header>> const&, int, std::vector<partData, std::allocator<partData>>&, fileMetrics&, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:735:41 #8 0x5672e9f2 in exrmetrics(char const*, char const*, int, Imf_3_4::Compression, float, int, bool, bool, PixelMode, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:1090:5 #9 0x56711f2d in main /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/main.cpp:540:41 #10 0xf78e7cb8 (/lib/i386-linux-gnu/libc.so.6+0x24cb8) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #11 0xf78e7d7b in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x24d7b) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #12 0x56630816 in _start (/home/br0nzu/openexr/v3.4.13/report/71. OpenEXR v3.4.13 exrmetrics ILP32 deep tiled sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0xb0816) (BuildId: 6bc8ac4c4e2527ef7300f003242cf56d2d5d03eb) 0xf72fe804 is located 0 bytes after 524292-byte region [0xf727e800,0xf72fe804) allocated by thread T0 here: #0 0x5670a5db in operator new(unsigned int) (/home/br0nzu/openexr/v3.4.13/report/71. OpenEXR v3.4.13 exrmetrics ILP32 deep tiled sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0x18a5db) (BuildId: 6bc8ac4c4e2527ef7300f003242cf56d2d5d03eb) #1 0x56736070 in std::__new_allocator<int>::allocate(unsigned int, void const*) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/new_allocator.h:151:27 #2 0x56736070 in std::allocator_traits<std::allocator<int>>::allocate(std::allocator<int>&, unsigned int) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/alloc_traits.h:482:20 #3 0x56736070 in std::_Vector_base<int, std::allocator<int>>::_M_allocate(unsigned int) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/stl_vector.h:381:20 #4 0x56736070 in std::vector<int, std::allocator<int>>::_M_default_append(unsigned int) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/vector.tcc:663:34 #5 0x56726abe in std::vector<int, std::allocator<int>>::resize(unsigned int) /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/stl_vector.h:1016:4 #6 0x56726abe in initAndReadDeepTiled(std::vector<int, std::allocator<int>>&, std::vector<std::vector<char, std::allocator<char>>, std::allocator<std::vector<char, std::allocator<char>>>>&, std::vector<std::vector<char*, std::allocator<char*>>, std::allocator<std::vector<char*, std::allocator<char*>>>>&, Imf_3_4::DeepFrameBuffer&, Imf_3_4::DeepTiledInputPart&, std::vector<int, std::allocator<int>> const*, Imf_3_4::Header const&, std::vector<double, std::allocator<double>>&, std::vector<double, std::allocator<double>>&) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:496:17 #7 0x567297e9 in initAndReadFile(Imf_3_4::MultiPartInputFile&, std::vector<Imf_3_4::Header, std::allocator<Imf_3_4::Header>> const&, int, std::vector<partData, std::allocator<partData>>&, fileMetrics&, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:735:41 #8 0x5672e9f2 in exrmetrics(char const*, char const*, int, Imf_3_4::Compression, float, int, bool, bool, PixelMode, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:1090:5 #9 0x56711f2d in main /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/main.cpp:540:41 #10 0xf78e7cb8 (/lib/i386-linux-gnu/libc.so.6+0x24cb8) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/br0nzu/openexr/v3.4.13/report/71. OpenEXR v3.4.13 exrmetrics ILP32 deep tiled sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0x145f41) (BuildId: 6bc8ac4c4e2527ef7300f003242cf56d2d5d03eb) in __asan_memcpy Shadow bytes around the buggy address: 0xf72fe580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf72fe600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf72fe680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf72fe700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf72fe780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0xf72fe800:[04]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf72fe880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf72fe900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf72fe980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf72fea00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf72fea80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==2995361==ABORTING timeout: the monitored command dumped coreFull UBSAN output
UndefinedBehaviorSanitizer:DEADLYSIGNAL ==2995365==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0xf790800c (pc 0xf7a7c430 bp 0xffd27198 sp 0xffd27028 T2995365) ==2995365==The signal is caused by a WRITE memory access. #0 0xf7a7c430 (/lib/i386-linux-gnu/libc.so.6+0x187430) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #1 0x56768cc7 in Imf_3_4::(anonymous namespace)::TileProcess::copy_sample_count(Imf_3_4::DeepFrameBuffer const*, int, int, int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:1238:13 #2 0x56768cc7 in Imf_3_4::(anonymous namespace)::TileProcess::run_decode(_priv_exr_context_t const*, int, Imf_3_4::DeepFrameBuffer const*, std::vector<Imf_3_4::DeepSlice, std::allocator<Imf_3_4::DeepSlice>> const&) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:1072:5 #3 0x5676433b in Imf_3_4::DeepTiledInputFile::Data::readTiles(int, int, int, int, int, int, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:968:20 #4 0x56766e37 in Imf_3_4::DeepTiledInputFile::readPixelSampleCounts(int, int, int, int, int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp:690:16 #5 0x566a188b in Imf_3_4::DeepTiledInputPart::readPixelSampleCounts(int, int, int, int, int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepTiledInputPart.cpp:200:11 #6 0x566902a8 in initAndReadDeepTiled(std::vector<int, std::allocator<int>>&, std::vector<std::vector<char, std::allocator<char>>, std::allocator<std::vector<char, std::allocator<char>>>>&, std::vector<std::vector<char*, std::allocator<char*>>, std::allocator<std::vector<char*, std::allocator<char*>>>>&, Imf_3_4::DeepFrameBuffer&, Imf_3_4::DeepTiledInputPart&, std::vector<int, std::allocator<int>> const*, Imf_3_4::Header const&, std::vector<double, std::allocator<double>>&, std::vector<double, std::allocator<double>>&) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:533:12 #7 0x56691211 in initAndReadFile(Imf_3_4::MultiPartInputFile&, std::vector<Imf_3_4::Header, std::allocator<Imf_3_4::Header>> const&, int, std::vector<partData, std::allocator<partData>>&, fileMetrics&, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:735:41 #8 0x56693cf2 in exrmetrics(char const*, char const*, int, Imf_3_4::Compression, float, int, bool, bool, PixelMode, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/exrmetrics.cpp:1090:5 #9 0x5668671b in main /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/main.cpp:540:41 #10 0xf7919cb8 (/lib/i386-linux-gnu/libc.so.6+0x24cb8) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #11 0xf7919d7b in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x24d7b) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #12 0x56651cf6 in _start (/home/br0nzu/openexr/v3.4.13/report/71. OpenEXR v3.4.13 exrmetrics ILP32 deep tiled sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_ubsan+0xefcf6) (BuildId: 309dd5e8b16594ca535230814439dc758b3e8668) UndefinedBehaviorSanitizer can not provide additional info. SUMMARY: UndefinedBehaviorSanitizer: SEGV (/lib/i386-linux-gnu/libc.so.6+0x187430) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) ==2995365==ABORTING timeout: the monitored command dumped coreImpact
Impact is ILP32-specific. Workflows that run ILP32
exrmetricson untrusted deep tiled EXR files can be crashed and can write sample-count data past a heap allocation.
Updates
2026-08-11 03:49 CEST
Metadata changes:
- Status for package
openexr: “Plausible”
2026-08-11 03:31 CEST
Metadata changes:
- Status for package
openexr: “New”