Skip to content

Commit 508d460

Browse files
committed
fix(softimage): validate channel packet maps
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
1 parent 165f18b commit 508d460

4 files changed

Lines changed: 106 additions & 2 deletions

File tree

‎src/softimage.imageio/softimageinput.cpp‎

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ SoftimageInput::open(const std::string& name, ImageSpec& spec)
110110

111111
// Get the ChannelPackets
112112
ChannelPacket curPacket;
113-
int nchannels = 0;
113+
int nchannels = 0;
114+
int bits_per_channel = 0;
115+
bool seen_channel[4] = { false, false, false, false };
114116
std::vector<std::string> encodings;
115117
do {
116118
// Read the next packet into curPacket and store it off
@@ -126,13 +128,61 @@ SoftimageInput::open(const std::string& name, ImageSpec& spec)
126128
close();
127129
return false;
128130
}
131+
132+
if (bits_per_channel == 0) {
133+
bits_per_channel = curPacket.size;
134+
} else if (curPacket.size != bits_per_channel) {
135+
errorfmt("Inconsistent bits per channel {}", curPacket.size);
136+
close();
137+
return false;
138+
}
139+
140+
if ((curPacket.type & 0x3) > MIXED_RUN_LENGTH) {
141+
errorfmt("Unsupported channel encoding {}",
142+
static_cast<int>(curPacket.type));
143+
close();
144+
return false;
145+
}
146+
147+
if (curPacket.channelCode
148+
& ~(RED_CHANNEL | GREEN_CHANNEL | BLUE_CHANNEL | ALPHA_CHANNEL)) {
149+
errorfmt("Unsupported channel code 0x{:x}",
150+
static_cast<int>(curPacket.channelCode));
151+
close();
152+
return false;
153+
}
154+
155+
std::vector<int> channels = curPacket.channels();
156+
if (channels.empty()) {
157+
errorfmt("Channel packet has no channels");
158+
close();
159+
return false;
160+
}
161+
162+
for (int channel : channels) {
163+
if (seen_channel[channel]) {
164+
errorfmt("Duplicate channel {} in channel packets", channel);
165+
close();
166+
return false;
167+
}
168+
seen_channel[channel] = true;
169+
}
170+
129171
m_channel_packets.push_back(curPacket);
130172

131173
// Add the number of channels in this packet to nchannels
132-
nchannels += curPacket.channels().size();
174+
nchannels += static_cast<int>(channels.size());
133175
encodings.push_back(encoding_name(m_channel_packets.back().type));
134176
} while (curPacket.chained);
135177

178+
for (int channel = 0; channel < nchannels; ++channel) {
179+
if (!seen_channel[channel]) {
180+
errorfmt("Sparse channel packets are not supported");
181+
close();
182+
return false;
183+
}
184+
}
185+
136186
// Get the depth per pixel per channel
137187
TypeDesc chanType = TypeDesc::UINT8;
138188
if (curPacket.size == 16)

‎testsuite/softimage/ref/out.txt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,6 @@ src/broken01.pic : 16 x 4, 1 channel, uint8 softimage
4444
Stats FiniteCount: 64
4545
Constant: No
4646
Monochrome: Yes
47+
sparse-alpha-uncompressed-rejected
48+
sparse-alpha-pure-rle-rejected
49+
sparse-alpha-mixed-rle-rejected

‎testsuite/softimage/run.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,15 @@
1313
# Regression testing of error handling and corrupt files
1414
command += info_command ("--stats src/broken01.pic",
1515
info_program="iinfo", failureok=True)
16+
17+
command += run_app (pythonbin + " src/make-sparse-channel-pics.py",
18+
silent=True)
19+
sparse_channel_files = [
20+
"sparse-alpha-uncompressed.pic",
21+
"sparse-alpha-pure-rle.pic",
22+
"sparse-alpha-mixed-rle.pic",
23+
]
24+
for f in sparse_channel_files:
25+
command += run_app ("(" + oiio_app("iconvert") + f
26+
+ " out.null > /dev/null 2>&1 "
27+
+ "|| echo " + f.replace(".pic", "-rejected") + ")")
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright Contributors to the OpenImageIO project.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# https://github.com/AcademySoftwareFoundation/OpenImageIO
6+
7+
import struct
8+
9+
10+
MAGIC = 0x5380F634
11+
WIDTH = 1
12+
HEIGHT = 1
13+
ALPHA_CHANNEL = 0x10
14+
15+
UNCOMPRESSED = 0
16+
PURE_RUN_LENGTH = 1
17+
MIXED_RUN_LENGTH = 2
18+
19+
20+
def header():
21+
comment = b"Sparse alpha channel regression"
22+
return struct.pack(">If80s4sHHfHH", MAGIC, 1.0, comment, b"PICT",
23+
WIDTH, HEIGHT, 1.0, 0, 0)
24+
25+
26+
def channel_packet(encoding):
27+
return bytes((0, 8, encoding, ALPHA_CHANNEL))
28+
29+
30+
def write_pic(filename, encoding, payload):
31+
with open(filename, "wb") as out:
32+
out.write(header())
33+
out.write(channel_packet(encoding))
34+
out.write(payload)
35+
36+
37+
write_pic("sparse-alpha-uncompressed.pic", UNCOMPRESSED, b"\x7f")
38+
write_pic("sparse-alpha-pure-rle.pic", PURE_RUN_LENGTH, b"\x01\x7f")
39+
write_pic("sparse-alpha-mixed-rle.pic", MIXED_RUN_LENGTH, b"\x00\x7f")

0 commit comments

Comments
 (0)