OpenEXR-viewer memory overflow vulnerability
Description
Memory overflow in OpenEXR-viewer prior to 0.6.1 due to integer overflow when allocating buffer for large image dimensions, fixed in version 0.6.1.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Memory overflow in OpenEXR-viewer prior to 0.6.1 due to integer overflow when allocating buffer for large image dimensions, fixed in version 0.6.1.
Vulnerability
CVE-2023-50245 is a memory overflow vulnerability in OpenEXR-viewer, a tool for viewing OpenEXR files. The issue arises from an integer overflow when calculating the buffer size needed for pixel data. Specifically, the product of image width and height (both 32-bit integers) can overflow, leading to an undersized allocation. This was fixed by adding a bounds check and switching from a raw pointer to std::vector for automatic memory management [1].
Exploitation
An attacker can trigger the vulnerability by crafting an OpenEXR file with excessively large dimensions (e.g., width and height such that their product exceeds 0x1FFFFFFF). When the file is opened, the defective code multiplies these values without validation, causing an integer overflow. A smaller buffer is allocated, and subsequent writes to pixel data overflow the buffer, corrupting adjacent memory [4].
Impact
Exploitation results in a write access violation, as demonstrated by crash logs showing an attempt to write the value 1.0 to an invalid memory address [4]. This memory corruption can lead to a denial of service (crash) or potentially arbitrary code execution if the attacker can control the overwritten data. The vulnerability is rated with a CVSS v3.1 score of 7.8 (High) due to the low complexity and potential for high impact on confidentiality, integrity, and availability [2].
Mitigation
The vulnerability is patched in OpenEXR-viewer version 0.6.1. Users should upgrade immediately. No workarounds are available; the fix involves proper bounds checking and use of safer data structures [1]. The project is open-source and actively maintained, with the fix available in the commit linked in the references.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
afichet/openexr-viewerGitHub Actions | < 0.6.1 | 0.6.1 |
Affected products
2- afichet/openexr-viewerv5Range: < 0.6.1
Patches
1d0a7e85dfeb5Early catch potential overflow issue #43
4 files changed · +43 −25
src/model/framebuffer/FramebufferModel.cpp+1 −5 modified@@ -39,7 +39,6 @@ FramebufferModel::FramebufferModel(QObject* parent) : QObject(parent) - , m_pixelBuffer(nullptr) , m_width(0) , m_height(0) , m_isImageLoaded(false) @@ -59,7 +58,4 @@ QRect FramebufferModel::getDataWindow() const return m_dataWindow; } -FramebufferModel::~FramebufferModel() -{ - delete[] m_pixelBuffer; -} +FramebufferModel::~FramebufferModel() {}
src/model/framebuffer/FramebufferModel.h+3 −3 modified@@ -37,7 +37,7 @@ #include <QObject> #include <QRect> #include <QVector> -#include <array> +#include <vector> class FramebufferModel: public QObject { @@ -67,8 +67,8 @@ class FramebufferModel: public QObject void loadFailed(QString message); protected: - float* m_pixelBuffer; - QImage m_image; + std::vector<float> m_pixelBuffer; + QImage m_image; // Right now, the width and height are defined as Vec2i in OpenEXR // i.e. int type.
src/model/framebuffer/RGBFramebufferModel.cpp+22 −13 modified@@ -81,6 +81,23 @@ void RGBFramebufferModel::load( m_displayWindow = QRect(dispW.min.x, dispW.min.y, dispW_width, dispW_height); + // Check to avoid type overflow, width and height are 32bits int + // representing a 2 dimentional image. Can overflow the type when + // multiplied together. + // 0x1FFFFFFF is a save limit for 4 * 0x7FFFFFFF the max + // representable int since we need 4 channels. + // TODO: Use larger type when manipulating framebuffer + const uint64_t partial_size + = (uint64_t)m_width * (uint64_t)m_height; + + if (partial_size > 0x1FFFFFFF) { + throw std::runtime_error( + "The total image size is too large. May be supported in a " + "future revision."); + } + + m_pixelBuffer.resize(4 * m_width * m_height); + // Check if there is specific chromaticities tied to the color // representation in this part. const Imf::ChromaticitiesAttribute* c @@ -93,8 +110,6 @@ void RGBFramebufferModel::load( chromaticities = c->value(); } - m_pixelBuffer = new float[4 * m_width * m_height]; - // Check if there is alpha channel if (hasAlpha) { std::string aLayer = m_parentLayer + "A"; @@ -190,12 +205,12 @@ void RGBFramebufferModel::load( Imf::FrameBuffer framebuffer; - Imf::Rgba* buff1 = new Imf::Rgba[m_width * m_height]; - Imf::Rgba* buff2 = new Imf::Rgba[m_width * m_height]; + std::vector<Imf::Rgba> buff1(m_width * m_height); + std::vector<Imf::Rgba> buff2(m_width * m_height); - float* yBuffer = new float[m_width * m_height]; - float* ryBuffer = new float[m_width / 2 * m_height / 2]; - float* byBuffer = new float[m_width / 2 * m_height / 2]; + std::vector<float> yBuffer(m_width * m_height); + std::vector<float> ryBuffer(m_width / 2 * m_height / 2); + std::vector<float> byBuffer(m_width / 2 * m_height / 2); Imf::Slice ySlice = Imf::Slice::Make( Imf::PixelType::FLOAT, @@ -335,12 +350,6 @@ void RGBFramebufferModel::load( m_pixelBuffer[4 * (y * m_width + x) + 2] = rgb.z; } } - - delete[] yBuffer; - delete[] ryBuffer; - delete[] byBuffer; - delete[] buff1; - delete[] buff2; } break;
src/model/framebuffer/YFramebufferModel.cpp+17 −4 modified@@ -90,12 +90,25 @@ void YFramebufferModel::load(Imf::MultiPartInputFile& file, int partId) dispW_width / 2, dispW_height / 2); - m_pixelBuffer = new float[m_width * m_height]; + // Check to avoid type overflow, width and height are 32bits int + // representing a 2 dimentional image. Can overflow the type when + // multiplied together + // TODO: Use larger type when manipulating framebuffer + const uint64_t partial_size + = (uint64_t)m_width * (uint64_t)m_height; + + if (partial_size > 0x7FFFFFFF) { + throw std::runtime_error( + "The total image size is too large. May be supported in " + "a future revision."); + } + + m_pixelBuffer.resize(m_width * m_height); // Luminance Chroma channels graySlice = Imf::Slice::Make( Imf::PixelType::FLOAT, - m_pixelBuffer, + m_pixelBuffer.data(), datW, sizeof(float), m_width * sizeof(float), @@ -112,11 +125,11 @@ void YFramebufferModel::load(Imf::MultiPartInputFile& file, int partId) m_displayWindow = QRect(dispW.min.x, dispW.min.y, dispW_width, dispW_height); - m_pixelBuffer = new float[m_width * m_height]; + m_pixelBuffer.resize(m_width * m_height); graySlice = Imf::Slice::Make( Imf::PixelType::FLOAT, - m_pixelBuffer, + m_pixelBuffer.data(), datW); }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-99jg-r3f4-rpxjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-50245ghsaADVISORY
- github.com/afichet/openexr-viewer/commit/d0a7e85dfeb519951fb8a8d70f73f30d41cdd3d9ghsax_refsource_MISCWEB
- github.com/afichet/openexr-viewer/security/advisories/GHSA-99jg-r3f4-rpxjghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.