High severity8.8NVD Advisory· Published May 7, 2026· Updated May 8, 2026
CVE-2026-41142
CVE-2026-41142
Description
OpenEXR provides the specification and reference implementation of the EXR file format, an image storage format for the motion picture industry. From versions 3.0.0 to before 3.2.9, 3.3.0 to before 3.3.11, and 3.4.0 to before 3.4.11, there is an integer overflow in ImageChannel::resize that leads to heap OOB write via OpenEXRUtil public API. This issue has been patched in versions 3.2.9, 3.3.11, and 3.4.11.
Affected products
1Patches
10592ee539f33Fix int overflow in ImageChannel::resize pixel count (#2367)
5 files changed · +116 −1
src/lib/OpenEXRUtil/ImfImageChannel.cpp+21 −1 modified@@ -13,6 +13,9 @@ #include "ImfImageLevel.h" #include <Iex.h> +#include <cstdint> +#include <limits> + using namespace IMATH_NAMESPACE; using namespace IEX_NAMESPACE; using namespace std; @@ -46,6 +49,13 @@ ImageChannel::channel () const void ImageChannel::resize () { + if (_xSampling < 1 || _ySampling < 1) + { + throw ArgExc ( + "The x and y sampling rates for an image channel must be at " + "least 1."); + } + const Box2i& dataWindow = level ().dataWindow (); if (dataWindow.min.x % _xSampling || dataWindow.min.y % _ySampling) @@ -67,7 +77,17 @@ ImageChannel::resize () _pixelsPerRow = width / _xSampling; _pixelsPerColumn = height / _ySampling; - _numPixels = _pixelsPerRow * _pixelsPerColumn; + + const uint64_t w64 = static_cast<uint64_t> (_pixelsPerRow); + const uint64_t h64 = static_cast<uint64_t> (_pixelsPerColumn); + const uint64_t maxPixels = + static_cast<uint64_t> (std::numeric_limits<size_t>::max ()); + if (w64 != 0 && h64 > maxPixels / w64) + { + throw ArgExc ("Image channel dimensions too large."); + } + + _numPixels = static_cast<size_t> (w64 * h64); } void
src/test/OpenEXRUtilTest/CMakeLists.txt+3 −0 modified@@ -9,6 +9,8 @@ add_executable(OpenEXRUtilTest testDeepImage.h testIO.cpp testIO.h + testImageChannel.cpp + testImageChannel.h ) target_include_directories(OpenEXRUtilTest PRIVATE ../OpenEXRTest) target_link_libraries(OpenEXRUtilTest OpenEXR::OpenEXRUtil) @@ -35,4 +37,5 @@ define_openexr_util_tests( testFlatImage testDeepImage testIO + testImageChannel )
src/test/OpenEXRUtilTest/main.cpp+2 −0 modified@@ -12,6 +12,7 @@ #include "testDeepImage.h" #include "testFlatImage.h" +#include "testImageChannel.h" #include "testIO.h" #include "tmpDir.h" #include <ImathRandom.h> @@ -89,6 +90,7 @@ main (int argc, char* argv[]) TEST (testFlatImage); TEST (testDeepImage); TEST (testIO); + TEST (testImageChannel); // NB: If you add a test here, make sure to enumerate it in the // CMakeLists.txt so it runs as part of the test suite
src/test/OpenEXRUtilTest/testImageChannel.cpp+82 −0 added@@ -0,0 +1,82 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) Contributors to the OpenEXR Project. +// + +#ifdef NDEBUG +# undef NDEBUG +#endif + +#include "testImageChannel.h" + +#include "ImfFlatImage.h" + +#include <Iex.h> +#include <ImathBox.h> + +#include <cassert> +#include <cstring> +#include <iostream> +#include <string> + +using namespace OPENEXR_IMF_NAMESPACE; +using namespace IMATH_NAMESPACE; +using namespace IEX_NAMESPACE; +using namespace std; + +namespace +{ + +// +// Sampling must be >= 1. ImageChannel::resize() rejects non-positive +// sampling before any modulo or division (so zero cannot invoke undefined +// behavior). Other invalid cases are still caught later in resize(). +// + +void +expectArgExcOnInsert (const char* label, int xSampling, int ySampling) +{ + FlatImage img (Box2i (V2i (0, 0), V2i (3, 3))); + + try + { + img.insertChannel ("bad", HALF, xSampling, ySampling, false); + cerr << "ERROR -- " << label << ": expected ArgExc, insert succeeded" + << endl; + assert (false); + } + catch (const ArgExc& e) + { + // Thrown at the start of ImageChannel::resize() so % and / never use + // a zero sampling rate (undefined behavior). + assert (strstr (e.what (), "at least 1") != nullptr); + } +} + +} // namespace + +void +testImageChannel (const string& tempDir) +{ + (void) tempDir; + + try + { + cout << "Testing ImageChannel sampling constraints" << endl; + + expectArgExcOnInsert ("negative xSampling", -1, 1); + expectArgExcOnInsert ("negative ySampling", 1, -1); + expectArgExcOnInsert ("negative x and y sampling", -1, -1); + + expectArgExcOnInsert ("zero xSampling", 0, 1); + expectArgExcOnInsert ("zero ySampling", 1, 0); + expectArgExcOnInsert ("zero x and y sampling", 0, 0); + + cout << "ok\n" << endl; + } + catch (const std::exception& e) + { + cerr << "ERROR -- caught exception: " << e.what () << endl; + assert (false); + } +}
src/test/OpenEXRUtilTest/testImageChannel.h+8 −0 added@@ -0,0 +1,8 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) Contributors to the OpenEXR Project. +// + +#include <string> + +void testImageChannel (const std::string& tempDir);
Vulnerability mechanics
AI mechanics synthesis has not run for this CVE yet.
References
3News mentions
0No linked articles in our index yet.