GHSA-g5m8-8w79-34q8
CVE Information
Summary
A malformed deep scanline EXR with a positive
65537 x 65537dataWindow can make the shippedexrmetricstool corrupt heap memory on ILP32 builds.initAndReadDeepScanLine()computesnumPixelsas 64-bit but passes it tostd::vector<int>::resize(size_type)for the deep sample-count table, which truncates on 32-bit builds. Fresh validation also reproduced the same behavior on current main.Details
The undersized
sampleCountvector is then exposed throughinsertSampleCountSlice().DeepScanLineInputPart::readPixelSampleCounts()copies sample-count data for the declared image into that truncated 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/70.\ OpenEXR\ v3.4.13\ exrmetrics\ ILP32\ deep\ scanline\ sampleCount\ heap\ buffer\ overflow/reproduce.shPoC input:
poc_materials/exrmetrics_deep_scanline_w65537_h65537_4rows_zero.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
================================================================= ==2607608==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf768b804 at pc 0x56777f42 bp 0xffef0258 sp 0xffeefe30 WRITE of size 262148 at 0xf768b804 thread T0 #0 0x56777f41 in __asan_memcpy (/home/br0nzu/openexr/v3.4.13/report/70. OpenEXR v3.4.13 exrmetrics ILP32 deep scanline sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0x145f41) (BuildId: 4fcf0d3fbc803d4d3c71bd09809b602f7950ff1d) #1 0x568c4cfe in Imf_3_4::(anonymous namespace)::ScanLineProcess::copy_sample_count(Imf_3_4::DeepFrameBuffer const*, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp:1030:13 #2 0x568c3b45 in Imf_3_4::(anonymous namespace)::ScanLineProcess::run_decode(_priv_exr_context_t const*, int, Imf_3_4::DeepFrameBuffer const*, int, int, 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/ImfDeepScanLineInputFile.cpp:835:5 #3 0x568bf563 in Imf_3_4::DeepScanLineInputFile::Data::readData(Imf_3_4::DeepFrameBuffer const&, int, int, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp:568:20 #4 0x568c2cd9 in Imf_3_4::DeepScanLineInputFile::readPixelSampleCounts(int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp:413:12 #5 0x567f87b3 in Imf_3_4::DeepScanLineInputPart::readPixelSampleCounts(int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp:78:11 #6 0x567d6539 in initAndReadDeepScanLine(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::DeepScanLineInputPart&, 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:367:12 #7 0x567dbca7 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:707:41 #8 0x567e09f2 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 0x567c3f2d in main /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/main.cpp:540:41 #10 0xf790dcb8 (/lib/i386-linux-gnu/libc.so.6+0x24cb8) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #11 0xf790dd7b in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x24d7b) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #12 0x566e2816 in _start (/home/br0nzu/openexr/v3.4.13/report/70. OpenEXR v3.4.13 exrmetrics ILP32 deep scanline sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0xb0816) (BuildId: 4fcf0d3fbc803d4d3c71bd09809b602f7950ff1d) 0xf768b804 is located 0 bytes after 524292-byte region [0xf760b800,0xf768b804) allocated by thread T0 here: #0 0x567bc5db in operator new(unsigned int) (/home/br0nzu/openexr/v3.4.13/report/70. OpenEXR v3.4.13 exrmetrics ILP32 deep scanline sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0x18a5db) (BuildId: 4fcf0d3fbc803d4d3c71bd09809b602f7950ff1d) #1 0x567e8070 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 0x567e8070 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 0x567e8070 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 0x567e8070 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 0x567d5f91 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 0x567d5f91 in initAndReadDeepScanLine(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::DeepScanLineInputPart&, 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:328:17 #7 0x567dbca7 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:707:41 #8 0x567e09f2 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 0x567c3f2d in main /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/main.cpp:540:41 #10 0xf790dcb8 (/lib/i386-linux-gnu/libc.so.6+0x24cb8) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/br0nzu/openexr/v3.4.13/report/70. OpenEXR v3.4.13 exrmetrics ILP32 deep scanline sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_asan+0x145f41) (BuildId: 4fcf0d3fbc803d4d3c71bd09809b602f7950ff1d) in __asan_memcpy Shadow bytes around the buggy address: 0xf768b580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf768b600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf768b680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf768b700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0xf768b780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0xf768b800:[04]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf768b880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf768b900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf768b980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf768ba00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0xf768ba80: 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 ==2607608==ABORTING timeout: the monitored command dumped coreFull UBSAN output
UndefinedBehaviorSanitizer:DEADLYSIGNAL ==2610362==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0xf797400c (pc 0xf7ae8430 bp 0xffd9e788 sp 0xffd9e6f8 T2610362) ==2610362==The signal is caused by a WRITE memory access. #0 0xf7ae8430 (/lib/i386-linux-gnu/libc.so.6+0x187430) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #1 0x5674bc13 in Imf_3_4::(anonymous namespace)::ScanLineProcess::copy_sample_count(Imf_3_4::DeepFrameBuffer const*, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp:1030:13 #2 0x5674ace1 in Imf_3_4::(anonymous namespace)::ScanLineProcess::run_decode(_priv_exr_context_t const*, int, Imf_3_4::DeepFrameBuffer const*, int, int, 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/ImfDeepScanLineInputFile.cpp:835:5 #3 0x56748435 in Imf_3_4::DeepScanLineInputFile::Data::readData(Imf_3_4::DeepFrameBuffer const&, int, int, bool) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp:568:20 #4 0x5674a47c in Imf_3_4::DeepScanLineInputFile::readPixelSampleCounts(int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp:413:12 #5 0x566a351f in Imf_3_4::DeepScanLineInputPart::readPixelSampleCounts(int, int) /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp:78:11 #6 0x56692164 in initAndReadDeepScanLine(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::DeepScanLineInputPart&, 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:367:12 #7 0x56694709 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:707:41 #8 0x56696cf2 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 0x5668971b in main /home/br0nzu/openexr/v3.4.13/sources/openexr-3.4.13/src/bin/exrmetrics/main.cpp:540:41 #10 0xf7985cb8 (/lib/i386-linux-gnu/libc.so.6+0x24cb8) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #11 0xf7985d7b in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x24d7b) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) #12 0x56654cf6 in _start (/home/br0nzu/openexr/v3.4.13/report/70. OpenEXR v3.4.13 exrmetrics ILP32 deep scanline sampleCount heap buffer overflow/repro_build/bin/exrmetrics_ilp32_ubsan+0xefcf6) (BuildId: 700d96bcc07342756ece50eb711df2698c60f790) UndefinedBehaviorSanitizer can not provide additional info. SUMMARY: UndefinedBehaviorSanitizer: SEGV (/lib/i386-linux-gnu/libc.so.6+0x187430) (BuildId: 0f6a23454651f08cb9b65ff6544d658177b59947) ==2610362==ABORTING timeout: the monitored command dumped coreImpact
Impact is ILP32-specific. Workflows that run ILP32
exrmetricson untrusted deep scanline EXR files can be crashed and can write sample-count data past a heap allocation.