From 7d6dff524c158d8ecd3fbff6771236498fde7efb Mon Sep 17 00:00:00 2001 From: Kimball Thurston Date: Tue, 19 Oct 2021 21:14:56 +1300 Subject: [PATCH] Fixes an issue computing the unpacked size of a chunk (#1184) This fixes an issue when the y_sampling is larger than the height of a chunk (and the height is not 1). Further, adds casts, use larger type to avoid overflow Signed-off-by: Kimball Thurston --- src/lib/OpenEXRCore/chunk.c | 7 ++++++- src/lib/OpenEXRCore/validation.c | 14 ++++++++++---- src/lib/OpenEXRUtil/ImfCheckFile.cpp | 4 +++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/lib/OpenEXRCore/chunk.c b/src/lib/OpenEXRCore/chunk.c index 24257176b6..875602c38f 100644 --- a/src/lib/OpenEXRCore/chunk.c +++ b/src/lib/OpenEXRCore/chunk.c @@ -178,7 +178,12 @@ compute_chunk_unpack_size ( if (curc->y_sampling > 1) { if (height > 1) - chansz /= ((uint64_t) curc->y_sampling); + { + if (curc->y_sampling > height) + chansz /= ((uint64_t) height); + else + chansz /= ((uint64_t) curc->y_sampling); + } else if ((y % ((int) curc->y_sampling)) != 0) chansz = 0; } diff --git a/src/lib/OpenEXRCore/validation.c b/src/lib/OpenEXRCore/validation.c index 8257b83d22..f067836a37 100644 --- a/src/lib/OpenEXRCore/validation.c +++ b/src/lib/OpenEXRCore/validation.c @@ -151,11 +151,17 @@ validate_image_dimensions ( /* isnormal will return true when par is 0, which should also be disallowed */ if (!isnormal (par) || par < 1e-6f || par > 1e+6f) return f->print_error ( - f, EXR_ERR_INVALID_ATTR, "Invalid pixel aspect ratio %g", (double)par); + f, + EXR_ERR_INVALID_ATTR, + "Invalid pixel aspect ratio %g", + (double) par); if (sww < 0.f) return f->print_error ( - f, EXR_ERR_INVALID_ATTR, "Invalid screen window width %g", (double)sww); + f, + EXR_ERR_INVALID_ATTR, + "Invalid screen window width %g", + (double) sww); return EXR_ERR_SUCCESS; } @@ -189,8 +195,8 @@ validate_channels ( "At least one channel required"); dw = curpart->data_window; - w = dw.max.x - dw.min.x + 1; - h = dw.max.y - dw.min.y + 1; + w = (int64_t) dw.max.x - (int64_t) dw.min.x + 1; + h = (int64_t) dw.max.y - (int64_t) dw.min.y + 1; for (int c = 0; c < channels->num_channels; ++c) { int32_t xsamp = channels->entries[c].x_sampling; diff --git a/src/lib/OpenEXRUtil/ImfCheckFile.cpp b/src/lib/OpenEXRUtil/ImfCheckFile.cpp index ad7ed2f760..c9ea2512c4 100644 --- a/src/lib/OpenEXRUtil/ImfCheckFile.cpp +++ b/src/lib/OpenEXRUtil/ImfCheckFile.cpp @@ -1181,9 +1181,11 @@ bool readCoreScanlinePart(exr_context_t f, int part, bool reduceMemory, bool red if (rv != EXR_ERR_SUCCESS) return true; - for (int y = datawin.min.y; y <= datawin.max.y; y += lines_per_chunk) + for (uint64_t chunk = 0; chunk < height; chunk += lines_per_chunk) { exr_chunk_info_t cinfo = { 0 }; + int y = ((int) chunk) + datawin.min.y; + rv = exr_read_scanline_chunk_info (f, part, y, &cinfo); if (rv != EXR_ERR_SUCCESS) {