VYPR
Critical severityNVD Advisory· Published Dec 11, 2023· Updated Aug 2, 2024

OpenEXR-viewer memory overflow vulnerability

CVE-2023-50245

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.

PackageAffected versionsPatched versions
afichet/openexr-viewerGitHub Actions
< 0.6.10.6.1

Affected products

2

Patches

1
d0a7e85dfeb5

Early catch potential overflow issue #43

https://github.com/afichet/openexr-viewerAlban FichetDec 9, 2023via ghsa
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

News mentions

0

No linked articles in our index yet.