Skip to content

GHSA-g5m8-8w79-34q8 on CTRL-OS 26.05

Aliases: GHSA-g5m8-8w79-34q8

Packages: openexr

Status: Plausible

Advisory Information

Summary

A malformed deep scanline EXR with a positive 65537 x 65537 dataWindow can make the shipped exrmetrics tool corrupt heap memory on ILP32 builds. initAndReadDeepScanLine() computes numPixels as 64-bit but passes it to std::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 sampleCount vector is then exposed through insertSampleCountSlice(). 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

poc.zip

From /home/br0nzu/openexr/v3.4.13:

./report/70.\ OpenEXR\ v3.4.13\ exrmetrics\ ILP32\ deep\ scanline\ sampleCount\ heap\ buffer\ overflow/reproduce.sh

PoC input: poc_materials/exrmetrics_deep_scanline_w65537_h65537_4rows_zero.exr

Validation 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_* and validation_summary.txt in this directory.

Original crash stderr:

timeout: the monitored command dumped core

Full 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 core

Full 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 core

Impact

Impact is ILP32-specific. Workflows that run ILP32 exrmetrics on untrusted deep scanline 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