Skip to content

GHSA-f667-c4wm-c8gq on CTRL-OS 26.05

Aliases: GHSA-f667-c4wm-c8gq

Packages: openexr

Status: Plausible

Advisory Information

Summary

A crafted tiled EXR can trigger a heap out-of-bounds write in OpenEXR v3.4.12 on 32-bit/ILP32 builds when read through the public TiledRgbaInputFile RGBA API. The file uses a small 40x40 dataWindow but a 65537x65537 tile size. On ILP32, the Array2D<Rgba> tile-conversion buffer size calculation overflows, allocates a much smaller heap buffer, and tile decode writes past that allocation.

Confirmed locally: the 32-bit original build crashes with SIGSEGV, ASAN reports a heap-buffer-overflow write, and UBSAN reports the signed integer overflow that causes the under-allocation.

Details

Root cause:

  • src/lib/OpenEXR/ImfTiledRgbaFile.cpp:599-604 copies TileDescription::xSize/ySize into _tileXSize/_tileYSize and calls _buf.resizeErase(_tileYSize, _tileXSize) for the FromYa conversion path.
  • src/lib/OpenEXR/ImfArray.h:212-218 allocates new T[sizeX * sizeY] without checked multiplication.
  • On ILP32, long is 32-bit, so 65537 * 65537 overflows to a small positive value before allocation.
  • src/lib/OpenEXRCore/unpack.c:1285, reached through TiledRgbaInputFile::readTile(), then writes decoded samples using tile-derived layout assumptions and overruns the under-sized heap buffer.

PoC header highlights:

dataWindow: (0, 0) - (39, 39)
channels: A, B, G, Y, all HALF
tile size: 65537 x 65537

Local verification with the attached file produced:

  • 32-bit original: SIGSEGV, rc=139
  • 32-bit ASAN: heap-buffer-overflow, WRITE of size 2
  • 32-bit UBSAN: signed integer overflow at ImfArray.h:214

PoC

Reproduction

poc.zip contains:

poc.zip

README.md
poc_ilp32_tiledrgba_xy_65537_abgy.exr
repro/repro_tiledrgba_readtile_ilp32.cpp
repro/build_repro.sh
repro/run_repro.sh

Run from the OpenEXR v3.4.12 workspace root after building the existing 32-bit OpenEXR variants under builds/ilp32_original, builds/ilp32_asan, and builds/ilp32_ubsan:

mkdir -p artifacts/tmp/report25-poc
unzip -o 'report/25. OpenEXR ILP32 TiledRgbaInputFile large tile Array2D heap OOB write/poc.zip' -d artifacts/tmp/report25-poc

artifacts/tmp/report25-poc/repro/build_repro.sh original
artifacts/tmp/report25-poc/repro/build_repro.sh asan
artifacts/tmp/report25-poc/repro/build_repro.sh ubsan

artifacts/tmp/report25-poc/repro/run_repro.sh original
artifacts/tmp/report25-poc/repro/run_repro.sh asan
artifacts/tmp/report25-poc/repro/run_repro.sh ubsan

Expected results:

original -> SIGSEGV, rc=139
ASAN    -> heap-buffer-overflow, WRITE of size 2
UBSAN   -> signed integer overflow: 65537 * 65537 cannot be represented in type 'long'

ASAN / UBSAN log excerpt

Representative ASAN output:

ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 2
    #0 generic_unpack src/lib/OpenEXRCore/unpack.c:1285
    #6 TiledRgbaInputFile::FromYa::readTile src/lib/OpenEXR/ImfTiledRgbaFile.cpp:669
allocated by:
    #1 Array2D<Rgba>::resizeErase(long,long) src/lib/OpenEXR/ImfArray.h:214
    #2 TiledRgbaInputFile::FromYa::FromYa src/lib/OpenEXR/ImfTiledRgbaFile.cpp:604

Representative UBSAN output:

src/lib/OpenEXR/ImfArray.h:214:26: runtime error: signed integer overflow: 65537 * 65537 cannot be represented in type 'long'

Impact

An attacker who can supply a crafted tiled EXR to an application using a 32-bit/ILP32 OpenEXR build and the public TiledRgbaInputFile tile-read API can trigger heap memory corruption during tile decoding. The confirmed impact is original-binary crash plus ASAN-confirmed heap out-of-bounds write on affected 32-bit builds.

Updates

2026-08-11 03:51 CEST

Metadata changes:

  • Status for package openexr: “Plausible

2026-08-11 03:30 CEST

Metadata changes:

  • Status for package openexr: “New