Skip to content

Commit 0100a54

Browse files
authored
Merge branch 'main' into nanobind-ci-integration
2 parents db6565a + 85cca81 commit 0100a54

1 file changed

Lines changed: 57 additions & 14 deletions

File tree

src/softimage.imageio/softimageinput.cpp

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class SoftimageInput final : public ImageInput {
5050
std::vector<softimage_pvt::ChannelPacket> m_channel_packets;
5151
std::string m_filename;
5252
std::vector<fpos_t> m_scanline_markers;
53+
// Maps absolute channel index (0=R,1=G,2=B,3=A) to sequential output
54+
// offset within the scanline buffer. Initialized to -1 (unused).
55+
int m_channel_map[4];
5356
};
5457

5558

@@ -76,6 +79,7 @@ SoftimageInput::init()
7679
m_filename.clear();
7780
m_channel_packets.clear();
7881
m_scanline_markers.clear();
82+
std::fill(m_channel_map, m_channel_map + 4, -1);
7983
}
8084

8185

@@ -110,7 +114,6 @@ SoftimageInput::open(const std::string& name, ImageSpec& spec)
110114

111115
// Get the ChannelPackets
112116
ChannelPacket curPacket;
113-
int nchannels = 0;
114117
std::vector<std::string> encodings;
115118
do {
116119
// Read the next packet into curPacket and store it off
@@ -126,13 +129,31 @@ SoftimageInput::open(const std::string& name, ImageSpec& spec)
126129
close();
127130
return false;
128131
}
132+
if (curPacket.channelCode == 0) {
133+
errorfmt("Channel packet with no channels");
134+
close();
135+
return false;
136+
}
129137
m_channel_packets.push_back(curPacket);
130138

131-
// Add the number of channels in this packet to nchannels
132-
nchannels += curPacket.channels().size();
133139
encodings.push_back(encoding_name(m_channel_packets.back().type));
140+
141+
if (m_channel_packets.size() > 4) {
142+
errorfmt("Too many channel packets");
143+
close();
144+
return false;
145+
}
134146
} while (curPacket.chained);
135147

148+
// Build channel map: absolute RGBA index -> sequential output offset
149+
int nchannels = 0;
150+
{
151+
for (auto& cp : m_channel_packets)
152+
for (int ch : cp.channels())
153+
if (m_channel_map[ch] == -1)
154+
m_channel_map[ch] = nchannels++;
155+
}
156+
136157
// Get the depth per pixel per channel
137158
TypeDesc chanType = TypeDesc::UINT8;
138159
if (curPacket.size == 16)
@@ -175,6 +196,8 @@ SoftimageInput::read_native_scanline(int subimage, int miplevel, int y,
175196
lock_guard lock(*this);
176197
if (!seek_subimage(subimage, miplevel))
177198
return false;
199+
if (y < 0 || y >= m_spec.height)
200+
return false;
178201

179202
bool result = false;
180203
if (y == (int)m_scanline_markers.size() - 1) {
@@ -271,9 +294,14 @@ SoftimageInput::read_next_scanline(void* data)
271294
ok = read_pixels_pure_run_length(cp, data);
272295
} else if (type == MIXED_RUN_LENGTH) {
273296
ok = read_pixels_mixed_run_length(cp, data);
297+
} else {
298+
errorfmt("Unsupported channel packet encoding {:d} in \"{}\"",
299+
int(cp.type), m_filename);
300+
close();
301+
return false;
274302
}
275303
if (!ok) {
276-
errorfmt("Failed to read channel packed type {:d} from \"{}\"",
304+
errorfmt("Failed to read channel packet type {:d} from \"{}\"",
277305
int(cp.type), m_filename);
278306
close();
279307
return false;
@@ -307,7 +335,8 @@ SoftimageInput::read_pixels_uncompressed(
307335
//read the data into the correct place
308336
if (fread(&scanlineData[(pixelX * pixelChannelSize
309337
* m_spec.nchannels)
310-
+ (channel * pixelChannelSize)
338+
+ (m_channel_map[channel]
339+
* pixelChannelSize)
311340
+ curByte],
312341
1, 1, m_fd)
313342
!= 1)
@@ -345,6 +374,12 @@ SoftimageInput::read_pixels_pure_run_length(
345374
if (fread(&curCount, 1, 1, m_fd) != 1)
346375
return false;
347376

377+
// Zero-length run is malformed
378+
if (curCount == 0) {
379+
errorfmt("Invalid RLE data");
380+
return false;
381+
}
382+
348383
// Clamp to avoid writing past the end of the scanline buffer
349384
if (linePixelCount + curCount > m_pic_header.width)
350385
curCount = m_pic_header.width - linePixelCount;
@@ -353,7 +388,7 @@ SoftimageInput::read_pixels_pure_run_length(
353388
// data pointer is set so we're supposed to write data there
354389
size_t pixelSize = pixelChannelSize * channels.size();
355390
uint8_t* pixelData = new uint8_t[pixelSize];
356-
if (fread(pixelData, pixelSize, 1, m_fd) != pixelSize)
391+
if (fread(pixelData, 1, pixelSize, m_fd) != pixelSize)
357392
return false;
358393

359394
// Now we've got the pixel value we need to push it into the data
@@ -370,7 +405,8 @@ SoftimageInput::read_pixels_pure_run_length(
370405
//put the data into the correct place
371406
scanlineData[(pixelX * pixelChannelSize
372407
* m_spec.nchannels)
373-
+ (channels[curChan] * pixelChannelSize)
408+
+ (m_channel_map[channels[curChan]]
409+
* pixelChannelSize)
374410
+ curByte]
375411
= pixelData[(curChan * pixelChannelSize) + curByte];
376412
}
@@ -432,12 +468,12 @@ SoftimageInput::read_pixels_mixed_run_length(
432468
curByte = ((pixelChannelSize)-1) - curByte;
433469

434470
//read the data into the correct place
435-
if (fread(
436-
&scanlineData[(pixelX * pixelChannelSize
437-
* m_spec.nchannels)
438-
+ (channel * pixelChannelSize)
439-
+ curByte],
440-
1, 1, m_fd)
471+
if (fread(&scanlineData[(pixelX * pixelChannelSize
472+
* m_spec.nchannels)
473+
+ (m_channel_map[channel]
474+
* pixelChannelSize)
475+
+ curByte],
476+
1, 1, m_fd)
441477
!= 1)
442478
return false;
443479
}
@@ -472,6 +508,12 @@ SoftimageInput::read_pixels_mixed_run_length(
472508
longCount = curCount - 127;
473509
}
474510

511+
// Zero-length run is malformed
512+
if (longCount == 0) {
513+
errorfmt("Invalid RLE data");
514+
return false;
515+
}
516+
475517
// Clamp to avoid writing past the end of the scanline buffer
476518
if (linePixelCount + longCount > m_pic_header.width)
477519
longCount = m_pic_header.width - linePixelCount;
@@ -500,7 +542,8 @@ SoftimageInput::read_pixels_mixed_run_length(
500542
//put the data into the correct place
501543
scanlineData[(pixelX * pixelChannelSize
502544
* m_spec.nchannels)
503-
+ (channels[curChan] * pixelChannelSize)
545+
+ (m_channel_map[channels[curChan]]
546+
* pixelChannelSize)
504547
+ curByte]
505548
= pixelData[(curChan * pixelChannelSize)
506549
+ curByte];

0 commit comments

Comments
 (0)