GHSA-fwhm-jj7c-mx7v
CVE Information
OpenEXR v3.4.13 deep NO_COMPRESSION scanline short sample data disclosure
Summary
A crafted deep scanline EXR using
NO_COMPRESSIONcan declare a deep sample-datapacked_sizesmaller thanunpacked_size. OpenEXRCore accepts the chunk, allocates the full unpack buffer, but no decompressor populates it forNO_COMPRESSION. The deep sample unpack path then copies stale internal allocation bytes into caller-visible deep sample output.This is file-triggered through public OpenEXRCore decode APIs with valid caller-provided deep sample buffers.
Reproduction status
v3.4.13 original/ASAN/UBSAN/MSAN: safe control rc=0, PoC rc=134 local main original/ASAN/UBSAN/MSAN: safe control rc=0, PoC rc=134 fresh origin/main 68203429 Release/ASAN: safe control rc=0, PoC rc=134PoC abort message in each failing run:
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytesThe abort is intentional in the harness after detecting allocator-pattern bytes in decoded deep sample output.
Root cause
Deep scanline chunk-info validates the deep sample-count table size and file bounds, but does not enforce the
NO_COMPRESSIONinvariant that packed sample data size must equal unpacked sample data size.Relevant flow:
src/lib/OpenEXRCore/chunk.c exr_read_scanline_chunk_info() deep scanline: reads sample_count_table_size, packed_size, unpacked_size missing: reject EXR_COMPRESSION_NONE when packed_size != unpacked_size src/lib/OpenEXRCore/decoding.c packed_size != unpacked_size -> allocate full unpacked_buffer EXR_COMPRESSION_NONE -> no decompressor fills that buffer deep unpack routine copies from unpacked_buffer into caller outputThe tiled path already has the missing guard for
NO_COMPRESSION; the deep scanline path does not.PoC package
poc.zipcontains only required reproduction material:reproduce.sh poc_materials/base_deep_none_4x1.exr poc_materials/poc_deep_none_short_4_of_16.exr poc_materials/fuzz_deep_none_short_uncompressed_api.cpp poc_materials/make_deep_scanline_seed.cpp poc_materials/patch_deep_none_short.py poc_materials/logs/final/summary.txt poc_materials/logs/final/reproduce_run.log poc_materials/logs/final/*_poc.errReproduction
From the extracted
poc.zipdirectory:OPENEXR_ROOT=/home/br0nzu/openexr/v3.4.13 ./reproduce.shExpected result: safe control files exit
0; the PoC exits134after the harness detects copied stale bytes.Complete validation output
The sanitizer builds do not emit an ASAN/UBSAN/MSAN stack trace here. The harness detects stale allocator-pattern bytes in caller-visible deep sample output and intentionally aborts, so the complete stderr for each sanitizer PoC run is the single line shown below.
reproduce.sh stdout
===== v3413_original_base ===== rc=0 ===== v3413_original_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== v3413_asan_base ===== rc=0 ===== v3413_asan_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== v3413_ubsan_base ===== rc=0 ===== v3413_ubsan_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== v3413_msan_base ===== rc=0 ===== v3413_msan_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== local_main_original_base ===== rc=0 ===== local_main_original_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== local_main_asan_base ===== rc=0 ===== local_main_asan_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== local_main_ubsan_base ===== rc=0 ===== local_main_ubsan_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== local_main_msan_base ===== rc=0 ===== local_main_msan_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== origin_main_682_release_base ===== rc=0 ===== origin_main_682_release_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes ===== origin_main_682_asan_base ===== rc=0 ===== origin_main_682_asan_poc ===== rc=134 DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytes PASSv3.4.13 ASAN PoC stderr
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytesv3.4.13 UBSAN PoC stderr
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytesv3.4.13 MSAN PoC stderr
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output byteslocal main ASAN PoC stderr
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output byteslocal main UBSAN PoC stderr
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output byteslocal main MSAN PoC stderr
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytesfresh origin/main 68203429 ASAN PoC stderr
DEEP NO_COMPRESSION short sample data leaked allocator pattern: 16/16 output bytesImpact
An attacker-controlled EXR file can cause decoded deep sample data to contain stale process memory bytes instead of file-provided sample data. Applications that decode and then display, convert, save, or transmit deep samples may expose those bytes.
This report demonstrates information disclosure.
Suggested fix
For deep scanline chunks, mirror the tiled-path check: reject
EXR_COMPRESSION_NONEchunks wherepacked_size != unpacked_size, or otherwise ensure the full unpack buffer is initialized before any deep sample unpack routine reads it.