CVE-2023-50245 (C++, published 2023-12-11T23:15Z)
Description: value: OpenEXR-viewer is a viewer for OpenEXR files with detailed metadata probing. Versions prior to 0.6.1 have a memory overflow vulnerability. This issue is fixed in version 0.6.1.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-120 \u2014 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
Repository: https://github.com/afichet/openexr-viewer
Files changed:
src/model/framebuffer/FramebufferModel.cpp
src/model/framebuffer/FramebufferModel.h
src/model/framebuffer/RGBFramebufferModel.cpp
src/model/framebuffer/YFramebufferModel.cpp
Commit message: Early catch potential overflow issue #43

`m_width` and `m_height` are of `int` type in the OpenEXR library. We
currently keep the same types in our class but this may case issue
when mapping 1D memory. In the most favorable case, they are
multiplied together (Y framebuffer). For RGB(A) case, the required
memory can also be 4 time larger. We check if resp. `m_width *
m_height` and `4 * m_width * m_heigh` stay within the `int` higher
limit. Thanks to @GAP-dev for bringing this issue.

This commit also cleans a bit raw memory allocation in favor of
`std::vector` container.


Vulnerable code:
  , m_pixelBuffer(nullptr)
FramebufferModel::~FramebufferModel()
{
    delete[] m_pixelBuffer;
}
#include <array>
    float* m_pixelBuffer;
    QImage m_image;
            m_pixelBuffer = new float[4 * m_width * m_height];

                    Imf::Rgba* buff1 = new Imf::Rgba[m_width * m_height];
                    Imf::Rgba* buff2 = new Imf::Rgba[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];

                    delete[] yBuffer;
                    delete[] ryBuffer;
                    delete[] byBuffer;
                    delete[] buff1;
                    delete[] buff2;
                m_pixelBuffer = new float[m_width * m_height];
                  m_pixelBuffer,
                m_pixelBuffer = new float[m_width * m_height];
                  m_pixelBuffer,

Fixed code:
FramebufferModel::~FramebufferModel() {}
#include <vector>
    std::vector<float> m_pixelBuffer;
    QImage             m_image;
            // 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);

                    std::vector<Imf::Rgba> buff1(m_width * m_height);
                    std::vector<Imf::Rgba> buff2(m_width * m_height);
                    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);
                // 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);
                  m_pixelBuffer.data(),
                m_pixelBuffer.resize(m_width * m_height);
                  m_pixelBuffer.data(),