Skip to content

Commit 8f315bd

Browse files
committed
fix(exr): Avoid integer overflow for large deep exr slice strides (#4542)
Fixes #4540 --------- Signed-off-by: Larry Gritz <[email protected]>
1 parent d952e22 commit 8f315bd

File tree

2 files changed

+39
-37
lines changed

2 files changed

+39
-37
lines changed

src/openexr.imageio/exrinput.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ OpenEXRInput::read_native_deep_scanlines(int subimage, int miplevel, int ybegin,
14851485
try {
14861486
size_t npixels = (yend - ybegin) * m_spec.width;
14871487
chend = clamp(chend, chbegin + 1, m_spec.nchannels);
1488-
int nchans = chend - chbegin;
1488+
size_t nchans = chend - chbegin;
14891489

14901490
// Set up the count and pointers arrays and the Imf framebuffer
14911491
std::vector<TypeDesc> channeltypes;
@@ -1502,16 +1502,17 @@ OpenEXRInput::read_native_deep_scanlines(int subimage, int miplevel, int ybegin,
15021502
sizeof(unsigned int),
15031503
sizeof(unsigned int) * m_spec.width);
15041504
frameBuffer.insertSampleCountSlice(countslice);
1505+
size_t slchans = m_spec.width * nchans;
1506+
size_t xstride = sizeof(void*) * nchans;
1507+
size_t ystride = sizeof(void*) * slchans;
1508+
size_t samplestride = deepdata.samplesize();
15051509

15061510
for (int c = chbegin; c < chend; ++c) {
1507-
Imf::DeepSlice slice(
1508-
part.pixeltype[c],
1509-
(char*)(&pointerbuf[0] + (c - chbegin) - m_spec.x * nchans
1510-
- ybegin * m_spec.width * nchans),
1511-
sizeof(void*) * nchans, // xstride of pointer array
1512-
sizeof(void*) * nchans
1513-
* m_spec.width, // ystride of pointer array
1514-
deepdata.samplesize()); // stride of data sample
1511+
Imf::DeepSlice slice(part.pixeltype[c],
1512+
(char*)(&pointerbuf[0] + (c - chbegin)
1513+
- m_spec.x * nchans
1514+
- ybegin * slchans),
1515+
xstride, ystride, samplestride);
15151516
frameBuffer.insert(m_spec.channelnames[c].c_str(), slice);
15161517
}
15171518
m_deep_scanline_input_part->setFrameBuffer(frameBuffer);
@@ -1564,7 +1565,7 @@ OpenEXRInput::read_native_deep_tiles(int subimage, int miplevel, int xbegin,
15641565
size_t height = yend - ybegin;
15651566
size_t npixels = width * height;
15661567
chend = clamp(chend, chbegin + 1, m_spec.nchannels);
1567-
int nchans = chend - chbegin;
1568+
size_t nchans = chend - chbegin;
15681569

15691570
// Set up the count and pointers arrays and the Imf framebuffer
15701571
std::vector<TypeDesc> channeltypes;
@@ -1579,14 +1580,15 @@ OpenEXRInput::read_native_deep_tiles(int subimage, int miplevel, int xbegin,
15791580
Imf::UINT, (char*)(&all_samples[0] - xbegin - ybegin * width),
15801581
sizeof(unsigned int), sizeof(unsigned int) * width);
15811582
frameBuffer.insertSampleCountSlice(countslice);
1583+
size_t slchans = width * nchans;
1584+
size_t xstride = sizeof(void*) * nchans;
1585+
size_t ystride = sizeof(void*) * slchans;
1586+
size_t samplestride = deepdata.samplesize();
15821587
for (int c = chbegin; c < chend; ++c) {
1583-
Imf::DeepSlice slice(
1584-
part.pixeltype[c],
1585-
(char*)(&pointerbuf[0] + (c - chbegin) - xbegin * nchans
1586-
- ybegin * width * nchans),
1587-
sizeof(void*) * nchans, // xstride of pointer array
1588-
sizeof(void*) * nchans * width, // ystride of pointer array
1589-
deepdata.samplesize()); // stride of data sample
1588+
Imf::DeepSlice slice(part.pixeltype[c],
1589+
(char*)(&pointerbuf[0] + (c - chbegin)
1590+
- xbegin * nchans - ybegin * slchans),
1591+
xstride, ystride, samplestride);
15901592
frameBuffer.insert(m_spec.channelnames[c].c_str(), slice);
15911593
}
15921594
m_deep_tiled_input_part->setFrameBuffer(frameBuffer);

src/openexr.imageio/exroutput.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,17 +1700,17 @@ OpenEXROutput::write_deep_scanlines(int ybegin, int yend, int /*z*/,
17001700
return false;
17011701
}
17021702

1703-
int nchans = m_spec.nchannels;
1703+
size_t nchans(m_spec.nchannels);
17041704
const DeepData* dd = &deepdata;
17051705
std::unique_ptr<DeepData> dd_local; // In case we need a copy
17061706
bool same_chantypes = true;
1707-
for (int c = 0; c < nchans; ++c)
1707+
for (size_t c = 0; c < nchans; ++c)
17081708
same_chantypes &= (m_spec.channelformat(c) == deepdata.channeltype(c));
17091709
if (!same_chantypes) {
17101710
// If the channel types don't match, we need to make a copy of the
17111711
// DeepData and convert the channels to the spec's channel types.
17121712
std::vector<TypeDesc> chantypes;
1713-
if (m_spec.channelformats.size() == size_t(nchans))
1713+
if (m_spec.channelformats.size() == nchans)
17141714
chantypes = m_spec.channelformats;
17151715
else
17161716
chantypes.resize(nchans, m_spec.format);
@@ -1729,15 +1729,15 @@ OpenEXROutput::write_deep_scanlines(int ybegin, int yend, int /*z*/,
17291729
frameBuffer.insertSampleCountSlice(countslice);
17301730
std::vector<void*> pointerbuf;
17311731
dd->get_pointers(pointerbuf);
1732-
for (int c = 0; c < nchans; ++c) {
1732+
size_t slchans = size_t(m_spec.width) * nchans;
1733+
size_t xstride = sizeof(void*) * nchans;
1734+
size_t ystride = sizeof(void*) * slchans;
1735+
size_t samplestride = dd->samplesize();
1736+
for (size_t c = 0; c < nchans; ++c) {
17331737
Imf::DeepSlice slice(m_pixeltype[c],
17341738
(char*)(&pointerbuf[c] - m_spec.x * nchans
1735-
- ybegin * m_spec.width * nchans),
1736-
sizeof(void*)
1737-
* nchans, // xstride of pointer array
1738-
sizeof(void*) * nchans
1739-
* m_spec.width, // ystride of pointer array
1740-
dd->samplesize()); // stride of data sample
1739+
- ybegin * slchans),
1740+
xstride, ystride, samplestride);
17411741
frameBuffer.insert(m_spec.channelnames[c].c_str(), slice);
17421742
}
17431743
m_deep_scanline_output_part->setFrameBuffer(frameBuffer);
@@ -1772,17 +1772,17 @@ OpenEXROutput::write_deep_tiles(int xbegin, int xend, int ybegin, int yend,
17721772
return false;
17731773
}
17741774

1775-
int nchans = m_spec.nchannels;
1775+
size_t nchans = size_t(m_spec.nchannels);
17761776
const DeepData* dd = &deepdata;
17771777
std::unique_ptr<DeepData> dd_local; // In case we need a copy
17781778
bool same_chantypes = true;
1779-
for (int c = 0; c < nchans; ++c)
1779+
for (size_t c = 0; c < nchans; ++c)
17801780
same_chantypes &= (m_spec.channelformat(c) == deepdata.channeltype(c));
17811781
if (!same_chantypes) {
17821782
// If the channel types don't match, we need to make a copy of the
17831783
// DeepData and convert the channels to the spec's channel types.
17841784
std::vector<TypeDesc> chantypes;
1785-
if (m_spec.channelformats.size() == size_t(nchans))
1785+
if (m_spec.channelformats.size() == nchans)
17861786
chantypes = m_spec.channelformats;
17871787
else
17881788
chantypes.resize(nchans, m_spec.format);
@@ -1803,15 +1803,15 @@ OpenEXROutput::write_deep_tiles(int xbegin, int xend, int ybegin, int yend,
18031803
frameBuffer.insertSampleCountSlice(countslice);
18041804
std::vector<void*> pointerbuf;
18051805
dd->get_pointers(pointerbuf);
1806-
for (int c = 0; c < nchans; ++c) {
1806+
size_t slchans = width * nchans;
1807+
size_t xstride = sizeof(void*) * nchans;
1808+
size_t ystride = sizeof(void*) * slchans;
1809+
size_t samplestride = dd->samplesize();
1810+
for (size_t c = 0; c < nchans; ++c) {
18071811
Imf::DeepSlice slice(m_pixeltype[c],
18081812
(char*)(&pointerbuf[c] - xbegin * nchans
1809-
- ybegin * width * nchans),
1810-
sizeof(void*)
1811-
* nchans, // xstride of pointer array
1812-
sizeof(void*) * nchans
1813-
* width, // ystride of pointer array
1814-
dd->samplesize()); // stride of data sample
1813+
- ybegin * slchans),
1814+
xstride, ystride, samplestride);
18151815
frameBuffer.insert(m_spec.channelnames[c].c_str(), slice);
18161816
}
18171817
m_deep_tiled_output_part->setFrameBuffer(frameBuffer);

0 commit comments

Comments
 (0)