Skip to content

Commit 6e8d62b

Browse files
authored
fix(softimage): Prevent buffer overruns from corrupt RLE (#5142)
* Check for buffer overruns. * Use check_open. * Check for invalid bit depths. Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent 6e1b493 commit 6e8d62b

4 files changed

Lines changed: 39 additions & 0 deletions

File tree

src/softimage.imageio/softimageinput.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ SoftimageInput::open(const std::string& name, ImageSpec& spec)
120120
close();
121121
return false;
122122
}
123+
// Some validity checking
124+
if (curPacket.size != 8 && curPacket.size != 16) {
125+
errorfmt("Unsupported bits per channel {}", curPacket.size);
126+
close();
127+
return false;
128+
}
123129
m_channel_packets.push_back(curPacket);
124130

125131
// Add the number of channels in this packet to nchannels
@@ -135,6 +141,12 @@ SoftimageInput::open(const std::string& name, ImageSpec& spec)
135141
// Set the details in the ImageSpec
136142
m_spec = ImageSpec(m_pic_header.width, m_pic_header.height, nchannels,
137143
chanType);
144+
145+
if (!check_open(m_spec, { 0, 65535, 0, 65535, 0, 1, 0, 4 })) {
146+
close();
147+
return false;
148+
}
149+
138150
m_spec.attribute("BitsPerSample", (int)curPacket.size);
139151

140152
m_spec.attribute("softimage:compression", Strutil::join(encodings, ","));
@@ -333,6 +345,10 @@ SoftimageInput::read_pixels_pure_run_length(
333345
if (fread(&curCount, 1, 1, m_fd) != 1)
334346
return false;
335347

348+
// Clamp to avoid writing past the end of the scanline buffer
349+
if (linePixelCount + curCount > m_pic_header.width)
350+
curCount = m_pic_header.width - linePixelCount;
351+
336352
if (data) {
337353
// data pointer is set so we're supposed to write data there
338354
size_t pixelSize = pixelChannelSize * channels.size();
@@ -456,6 +472,10 @@ SoftimageInput::read_pixels_mixed_run_length(
456472
longCount = curCount - 127;
457473
}
458474

475+
// Clamp to avoid writing past the end of the scanline buffer
476+
if (linePixelCount + longCount > m_pic_header.width)
477+
longCount = m_pic_header.width - linePixelCount;
478+
459479
if (data) {
460480
// data pointer is set so we're supposed to write data there
461481
size_t pixelSize = pixelChannelSize * channels.size();

testsuite/softimage/ref/out.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,17 @@ Reading ../oiio-images/softimage/astone64.pic
3030
Stats FiniteCount: 4096 4096 4096
3131
Constant: No
3232
Monochrome: No
33+
src/broken01.pic : 16 x 4, 1 channel, uint8 softimage
34+
SHA-1: 0526ABB83138E5FD9BC07BB83035C89028527301
35+
channel list: Y
36+
BitsPerSample: 8
37+
softimage:compression: "mixed-rle"
38+
Stats Min: 0 (of 255)
39+
Stats Max: 65 (of 255)
40+
Stats Avg: 16.25 (of 255)
41+
Stats StdDev: 28.15 (of 255)
42+
Stats NanCount: 0
43+
Stats InfCount: 0
44+
Stats FiniteCount: 64
45+
Constant: No
46+
Monochrome: Yes

testsuite/softimage/run.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
# SPDX-License-Identifier: Apache-2.0
55
# https://github.com/AcademySoftwareFoundation/OpenImageIO
66

7+
redirect = ' >> out.txt 2>&1 '
8+
79
files = [ "A4.pic", "astone64.pic" ]
810
for f in files:
911
command += info_command (OIIO_TESTSUITE_IMAGEDIR + "/" + f, extraargs="--stats")
1012

13+
# Regression testing of error handling and corrupt files
14+
command += info_command ("--stats src/broken01.pic",
15+
info_program="iinfo", failureok=True)
163 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)