Fix: Integer overflow when saving large EXR images

Various intermediate calculations would overflow inside both
`imb_save_openexr_float` and `imb_save_openexr_half`.

Additionally, use a raw array for the half conversion since `vector`
will perform an unnecessary zero-initialize on a large amount of memory.

Refer to: #135648

Pull Request: https://projects.blender.org/blender/blender/pulls/135678
This commit is contained in:
Jesse Yurkovich
2025-03-10 22:01:33 +01:00
committed by Jesse Yurkovich
parent 3fe61d1b22
commit 5b26ae10a6
@@ -502,8 +502,8 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *filepath, const int f
OutputFile file(*file_stream, header);
/* we store first everything in half array */
std::vector<RGBAZ> pixels(height * width);
RGBAZ *to = pixels.data();
std::unique_ptr<RGBAZ[]> pixels = std::unique_ptr<RGBAZ[]>(new RGBAZ[int64_t(height) * width]);
RGBAZ *to = pixels.get();
int xstride = sizeof(RGBAZ);
int ystride = xstride * width;
@@ -518,7 +518,7 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *filepath, const int f
float *from;
for (int i = ibuf->y - 1; i >= 0; i--) {
from = ibuf->float_buffer.data + channels * i * width;
from = ibuf->float_buffer.data + int64_t(channels) * i * width;
for (int j = ibuf->x; j > 0; j--) {
to->r = float_to_half_safe(from[0]);
@@ -534,7 +534,7 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *filepath, const int f
uchar *from;
for (int i = ibuf->y - 1; i >= 0; i--) {
from = ibuf->byte_buffer.data + 4 * i * width;
from = ibuf->byte_buffer.data + int64_t(4) * i * width;
for (int j = ibuf->x; j > 0; j--) {
to->r = srgb_to_linearrgb(float(from[0]) / 255.0f);
@@ -608,7 +608,7 @@ static bool imb_save_openexr_float(ImBuf *ibuf, const char *filepath, const int
/* Last scan-line, stride negative. */
float *rect[4] = {nullptr, nullptr, nullptr, nullptr};
rect[0] = ibuf->float_buffer.data + channels * (height - 1) * width;
rect[0] = ibuf->float_buffer.data + int64_t(channels) * (height - 1) * width;
rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0];
rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0];
rect[3] = (channels >= 4) ?