Skip to content

Commit c48f23c

Browse files
authored
PXR24: reject zlib output that does not match packed payload size (#2310)
* PXR24: reject zlib output that does not match packed payload size PXR24 stores zlib-compressed packed channel data (e.g. 3 bytes/sample for float), while chunk `unpacked_size` is the native layout (4 bytes/sample). After inflate, validate the decompressed length against the packed byte count derived from the same geometry as encode/decode, not `unpacked_size`. A truncated-but-valid zlib stream previously produced success with a short `actual_out` while the decoder advanced through scratch as if the full packed block were present, reading uninitialized heap into pixels. Add `pxr24_packed_zlib_size()` (aligned with `apply_pxr24_impl`) and require `outSize ==` that value after `exr_uncompress_buffer()` succeeds. Analysis and solution with the the help of Cursor / Claude Opus 4.5 Signed-off-by: Cary Phillips <cary@ilm.com> * replace comparison to uncompressed_size with outSize A simpler solution: remove `pxr24_packed_zlib_size()` entirely detect corrupt chunks by comparing against `outSize` instead of `uncompressed_size`. Signed-off-by: Cary Phillips <cary@ilm.com> --------- Signed-off-by: Cary Phillips <cary@ilm.com>
1 parent 6155271 commit c48f23c

2 files changed

Lines changed: 8 additions & 4 deletions

File tree

src/lib/OpenEXRCore/compression.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@ exr_uncompress_buffer (
201201
}
202202
else if (res == LIBDEFLATE_SHORT_OUTPUT)
203203
{
204-
/* TODO: is this an error? */
204+
/* Decompression succeeded; *actual_out is the byte count. This is
205+
* not an error when out_bytes_avail exceeds the true uncompressed
206+
* size (e.g. PXR24/ZIP use padded scratch buffers). Callers that
207+
* need an exact payload size must compare *actual_out (see e.g.
208+
* undo_pxr24_impl). */
205209
return EXR_ERR_SUCCESS;
206210
}
207211
return EXR_ERR_CORRUPT_CHUNK;

src/lib/OpenEXRCore/internal_pxr24.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ undo_pxr24_impl (
320320
ptr[3] = lastIn;
321321
lastIn += w;
322322

323-
if (nDec + nBytes > uncompressed_size)
323+
if (nDec + nBytes > outSize)
324324
return EXR_ERR_CORRUPT_CHUNK;
325325

326326
for (int x = 0; x < w; ++x)
@@ -347,7 +347,7 @@ undo_pxr24_impl (
347347
ptr[1] = lastIn;
348348
lastIn += w;
349349

350-
if (nDec + nBytes > uncompressed_size)
350+
if (nDec + nBytes > outSize)
351351
return EXR_ERR_CORRUPT_CHUNK;
352352

353353
for (int x = 0; x < w; ++x)
@@ -374,7 +374,7 @@ undo_pxr24_impl (
374374
ptr[2] = lastIn;
375375
lastIn += w;
376376

377-
if (nDec + (uint64_t) (w * 3) > uncompressed_size)
377+
if (nDec + (uint64_t) (w * 3) > outSize)
378378
return EXR_ERR_CORRUPT_CHUNK;
379379

380380
for (int x = 0; x < w; ++x)

0 commit comments

Comments
 (0)