Skip to content

GHSA-hwmv-39v6-739m on CTRL-OS 26.05

Aliases: GHSA-hwmv-39v6-739m

Packages: openexr

Status: Plausible

Advisory Information

Summary

OpenEXRUtil v3.4.12 can return an out-of-bounds pointer from the documented TypedDeepImageChannel<T>::row(row) API when a deep image has a non-zero dataWindow origin. The primary PoC crashes the original build with SIGSEGV, ASAN reports a heap out-of-bounds read, and UBSAN reaches the same row-pointer read path.

A separate original-build marker probe demonstrates potential information disclosure under a controlled heap layout: row(0)[idx] can read a later heap pointer slot and expose a synthetic marker value

Details

Root cause:

  • src/lib/OpenEXRUtil/ImfDeepImageChannel.h:141-152 documents row(r) as 0-based row access.
  • src/lib/OpenEXRUtil/ImfDeepImageChannel.h:247-258 returns _base + r * pixelsPerRow().
  • src/lib/OpenEXRUtil/ImfDeepImageChannel.cpp:275-279 sets _base to _sampleListPointers - dataWindow.min.y * pixelsPerRow() - dataWindow.min.x for absolute-coordinate at(x,y) access.

Those two coordinate models conflict for non-zero dataWindow.min. at(dataWindow.min.x, dataWindow.min.y) is valid, but documented row(0) should start at the first logical row and instead points outside the _sampleListPointers allocation.

Primary PoC input:

file: poc_deep_channel_row_ptr_minx1024_minyneg1024.exr
dataWindow: (1024, -1024) - (1031, -1017)
channel: Z, FLOAT
type: deepscanline

Local verification:

original primary -> SIGSEGV, rc=139
ASAN primary     -> heap-buffer-overflow READ, rc=134
UBSAN primary    -> DEADLYSIGNAL on the row pointer path, rc=134
MSAN primary     -> pre-input static-initialization report, rc=134
original marker  -> marker-scan HIT, rc=77

PoC

poc.zip contains only the reproducible PoC files, helper sources/scripts, and fresh logs:

poc.zip

README.md
poc_deep_channel_row_ptr_minx1024_minyneg1024.exr
marker19.exr
repro/repro_deep_channel_row_read.cpp
repro/probe_deep_row_pointer_marker.cpp
repro/build_repro.sh
repro/run_repro.sh
logs/original_primary.log
logs/asan_primary.log
logs/ubsan_primary.log
logs/msan_primary.log
logs/original_marker_recheck.log

Run from the OpenEXR v3.4.12 workspace root:

mkdir -p artifacts/tmp/report19-poc
unzip -o 'report/19. OpenEXRUtil DeepImageChannel row nonzero dataWindow heap OOB read/poc.zip' -d artifacts/tmp/report19-poc

artifacts/tmp/report19-poc/repro/build_repro.sh "$PWD" original
artifacts/tmp/report19-poc/repro/build_repro.sh "$PWD" asan
artifacts/tmp/report19-poc/repro/build_repro.sh "$PWD" ubsan
artifacts/tmp/report19-poc/repro/build_repro.sh "$PWD" msan

artifacts/tmp/report19-poc/repro/run_repro.sh "$PWD" original primary
artifacts/tmp/report19-poc/repro/run_repro.sh "$PWD" asan primary
artifacts/tmp/report19-poc/repro/run_repro.sh "$PWD" ubsan primary
artifacts/tmp/report19-poc/repro/run_repro.sh "$PWD" msan primary
artifacts/tmp/report19-poc/repro/run_repro.sh "$PWD" original marker

ASAN excerpt:

ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 8
#0 main artifacts/tmp/report19-poc/repro/repro_deep_channel_row_read.cpp:31:16
SUMMARY: AddressSanitizer: heap-buffer-overflow ... repro_deep_channel_row_read.cpp:31:16 in main

UBSAN excerpt:

UndefinedBehaviorSanitizer:DEADLYSIGNAL
The signal is caused by a READ memory access.
#0 main artifacts/tmp/report19-poc/repro/repro_deep_channel_row_read.cpp:31:16
SUMMARY: UndefinedBehaviorSanitizer: SEGV ... repro_deep_channel_row_read.cpp:31:16 in main

Original marker probe excerpt:

marker-scan miny=-483
miny=-483 w=8 h=8 ... row_to_slots_idx=4 HIT idx=4 ... value=31564.000000 expected=31564.000000

Impact

An application that accepts a crafted deep EXR, loads it with OpenEXRUtil, and uses TypedDeepImageChannel<T>::row(row) can be crashed by a heap out-of-bounds read. The marker probe also shows potential information disclosure when surrounding heap layout makes the out-of-bounds pointer array entry application-observable. The safe claim is heap out-of-bounds read / crash with potential information disclosure; arbitrary read address control, real sensitive-data disclosure, writes, and code execution were not demonstrated.

Updates

2026-08-11 03:50 CEST

Metadata changes:

  • Status for package openexr: “Plausible

2026-08-11 03:30 CEST

Metadata changes:

  • Status for package openexr: “New