Описание
OpenEXR's CompositeDeepScanLine integer-overflow leads to heap OOB write
Summary
Function: CompositeDeepScanLine::readPixels, reachable from high-level multipart deep read flows (MultiPartInputFile + DeepScanLineInputPart + CompositeDeepScanLine).
Vulnerable lines (src/lib/OpenEXR/ImfCompositeDeepScanLine.cpp):
total_sizes[ptr] += counts[j][ptr];(line ~511)overall_sample_count += total_sizes[ptr];(line ~514)samples[channel].resize (overall_sample_count);(line ~535)
Impact: 32-bit sample-count accumulation wrap leads to undersized allocation, then decode writes with true sample volume, causing heap OOB write in generic_unpack_deep_pointers (src/lib/OpenEXRCore/unpack.c:1374) (DoS/Crash, memory corruption/RCE).
Attack scenario:
- Attacker provides multipart deep EXR with many parts and very large sample counts per pixel.
- Uses compression (RLE/ZIPS) to keep file size relatively small vs decode pressure.
- The overflow happens in composite sample accounting (
unsigned int), while pointer progression for decode uses larger counters and reaches out-of-bounds.
Tested on: OpenEXR 4.0.0-dev (commit 83449669402080874b25ff1fa740649a9e6ea064) but this code has existed since v2.3.0
Steps to reproduce
composite_deepscanline_poc_bundle.patch
PoC files used:
- Writer/generator:
poc/composite_deep_scanline_e2e_compressed_poc.cpp - Minimal high-level reader harness:
poc/simple_exr_reader.cpp
The reader harness intentionally mimics realistic app behavior: open EXR, iterate parts, select DEEPSCANLINE, add sources to CompositeDeepScanLine, bind a normal FrameBuffer, then call readPixels.
Build with ASAN/UBSAN:
Generate malicious file (decode-path focused profile):
Trigger:
ASAN builds are slower. If needed, a non-sanitized build + debugger is faster for iteration.
Example runs
Writer (abbrev):
Reader ASAN crash:
Root cause analysis
In CompositeDeepScanLine::readPixels:
- Per-pixel totals are accumulated in
vector<unsigned int> total_sizes. - For attacker-controlled large counts across many parts,
total_sizes[ptr]wraps modulo2^32. overall_sample_countis then derived from wrapped totals and used insamples[channel].resize(overall_sample_count).- Decode pointer setup/consumption proceeds with true sample counts, and write operations in core unpack (
generic_unpack_deep_pointers) overrun the undersized composite sample buffer.
Allocation is based on a tiny wrapped value, but decode writes correspond to the true large sample volume.
Impact
Heap OOB write during decode. This is at minimum a reliable crash/DoS. As heap corruption, this bug could be used for potential remote code execution.
Пакеты
OpenEXR
>= 2.3.0, < 3.2.6
3.2.6
OpenEXR
>= 3.3.0, < 3.3.8
3.3.8
OpenEXR
>= 3.4.0, < 3.4.6
3.4.6
Связанные уязвимости
OpenEXR provides the specification and reference implementation of the EXR file format, an image storage format for the motion picture industry. In CompositeDeepScanLine::readPixels, per-pixel totals are accumulated in vector<unsigned int> total_sizes for attacker-controlled large counts across many parts, total_sizes[ptr] wraps modulo 2^32. overall_sample_count is then derived from wrapped totals and used in samples[channel].resize(overall_sample_count). Decode pointer setup/consumption proceeds with true sample counts, and write operations in core unpack (generic_unpack_deep_pointers) overrun the undersized composite sample buffer. This vulnerability is fixed in v3.2.6, v3.3.8, and v3.4.6.
OpenEXR provides the specification and reference implementation of the EXR file format, an image storage format for the motion picture industry. In CompositeDeepScanLine::readPixels, per-pixel totals are accumulated in vector<unsigned int> total_sizes for attacker-controlled large counts across many parts, total_sizes[ptr] wraps modulo 2^32. overall_sample_count is then derived from wrapped totals and used in samples[channel].resize(overall_sample_count). Decode pointer setup/consumption proceeds with true sample counts, and write operations in core unpack (generic_unpack_deep_pointers) overrun the undersized composite sample buffer. This vulnerability is fixed in v3.2.6, v3.3.8, and v3.4.6.
OpenEXR provides the specification and reference implementation of the EXR file format, an image storage format for the motion picture industry. In CompositeDeepScanLine::readPixels, per-pixel totals are accumulated in vector<unsigned int> total_sizes for attacker-controlled large counts across many parts, total_sizes[ptr] wraps modulo 2^32. overall_sample_count is then derived from wrapped totals and used in samples[channel].resize(overall_sample_count). Decode pointer setup/consumption proceeds with true sample counts, and write operations in core unpack (generic_unpack_deep_pointers) overrun the undersized composite sample buffer. This vulnerability is fixed in v3.2.6, v3.3.8, and v3.4.6.
OpenEXR provides the specification and reference implementation of the ...