GitHub Security Advisory: GHSA-cr4v-6jm6-4963
Package: OpenEXR (PIP)
Severity: HIGH (CVSS 0.0)
CWE: CWE-787: Out-of-bounds Write
Vulnerable versions: >= 3.4.0, < 3.4.6
Patched in: 3.4.6

Summary: OpenEXR's CompositeDeepScanLine integer-overflow leads to heap OOB write

Details:
## 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[PII_REDACTED]2080874b25ff1fa740649a9e6ea064) but this code has existed since v2.3.0

## Steps to reproduce

[composite_deepscanline_poc_bundle.patch](https://github.com/user-attachments/files/25383205/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:

```bash
cmake -S . -B build-asan \
  -DOPENEXR_BUILD_POC=ON \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DCMAKE_C_FLAGS='-fsanitize=address,undefined -fno-omit-frame-pointer' \
  -DCMAKE_CXX_FLAGS='-fsanitize=address,undefined -fno-omit-frame-pointer' \
  -DCMAKE_EXE_LINKER_FLAGS='-fsanitize=address,undefined' \
  -DCMAKE_SHARED_LINKER_FLAGS='-fsanitize=address,undefined'

cmake --build build-asan --target composite_writer simple_exr_reader -j
```

Generate malicious file (decode-path focused profile):

```bash
ASAN_OPTIONS=detect_leaks=0 timeout 180s \
  ./build-asan/poc/composite_writer \
  --profile low-ram \
  --file /tmp/composite_decode_focus.exr
```

Trigger:

```bash
ASAN_OPTIONS=detect_leaks=0 timeout 30s \
  ./build-asan/poc/simple_exr_reader /tmp/composite_decode_focus.exr
```

ASAN builds are slower. If needed, a non-sanitized build + debugger is faster for iteration.

## Example runs

Writer (abbrev):

```bash
❯ ./build-asan/poc/composite_writer
exploit math:
  benign samples                 : 300
  malicious parts                : 86
  malicious samples per part     : 50000000
  true total samples             :[PII_REDACTED]
  uint32 overflow reached        : yes
  wrapped uint32 total           : 5033004
  composite Z/A alloc from wrap  : 40264032 bytes (38.40 MiB)