diff --git a/src/rla.imageio/rlainput.cpp b/src/rla.imageio/rlainput.cpp index b71c9d4e39..bfd667ae3d 100644 --- a/src/rla.imageio/rlainput.cpp +++ b/src/rla.imageio/rlainput.cpp @@ -86,11 +86,11 @@ class RLAInput final : public ImageInput { bool decode_channel_group(int first_channel, short num_channels, short num_bits, int y); - /// Helper: decode a span of n RLE-encoded bytes from encoded[0..elen-1] + /// Helper: decode a span of n RLE-encoded bytes from encoded[] /// into buf[0],buf[stride],buf[2*stride]...buf[(n-1)*stride]. /// Return the number of encoded bytes we ate to fill buf. - size_t decode_rle_span(unsigned char* buf, int n, int stride, - const char* encoded, size_t elen); + size_t decode_rle_span(span buf, int n, int stride, + cspan encoded); /// Helper: determine channel TypeDesc inline TypeDesc get_channel_typedesc(short chan_type, short chan_bits); @@ -245,10 +245,11 @@ RLAInput::seek_subimage(int subimage, int miplevel) ioseek(0); if (!read_header()) return false; // read_header always calls error() - diff = subimage; + diff = subimage; + m_subimage = 0; } // forward scrolling -- skip subimages until we're at the right place - while (diff > 0 && m_rla.NextOffset != 0) { + while (diff > 0 && m_subimage < subimage && m_rla.NextOffset != 0) { if (!ioseek(m_rla.NextOffset)) { errorfmt("Could not seek to header offset. Corrupted file?"); return false; @@ -256,6 +257,7 @@ RLAInput::seek_subimage(int subimage, int miplevel) if (!read_header()) return false; // read_header always calls error() --diff; + ++m_subimage; } if (diff > 0 && m_rla.NextOffset == 0) { // no more subimages to read errorfmt("Unknown subimage"); @@ -490,23 +492,28 @@ RLAInput::close() size_t -RLAInput::decode_rle_span(unsigned char* buf, int n, int stride, - const char* encoded, size_t elen) +RLAInput::decode_rle_span(span buf, int n, int stride, + cspan encoded) { - size_t e = 0; + size_t e = 0; // position we're reading in encoded + size_t elen = encoded.size(); // Number of encoded bytes to decode + size_t b = 0; // postition we're writing in buf while (n > 0 && e < elen) { int count = (signed char)encoded[e++]; if (count >= 0) { // run count positive: value repeated count+1 times - for (int i = 0; i <= count && n && e < elen; - ++i, buf += stride, --n) - *buf = encoded[e]; + if (count + 1 > n) + break; // asking for a count that will overrun the buffer + for (int i = 0; i <= count; ++i, b += stride, --n) + buf[b] = encoded[e]; ++e; } else { // run count negative: repeat bytes literally + if (count > n) + break; // asking for a count that will overrun the buffer count = -count; // make it positive - for (; count && n > 0 && e < elen; --count, buf += stride, --n) - *buf = encoded[e++]; + for (; count && n > 0 && e < elen; --count, b += stride, --n) + buf[b] = encoded[e++]; } } if (n != 0) { @@ -540,7 +547,7 @@ RLAInput::decode_channel_group(int first_channel, short num_channels, offset = 0; pixelsize = m_spec.pixel_bytes(true); for (int i = 0; i < first_channel; ++i) - offset += m_spec.channelformats[i].size(); + offset += m_spec.channelformat(i).size(); } // Read the big-endian values into the buffer. @@ -583,9 +590,10 @@ RLAInput::decode_channel_group(int first_channel, short num_channels, // and strides to decode_rle_span. size_t eoffset = 0; for (int bytes = 0; bytes < chsize && length > 0; ++bytes) { - size_t e = decode_rle_span(&m_buf[offset + c * chsize + bytes], + size_t e = decode_rle_span(make_span(m_buf).subspan( + offset + c * chsize + bytes), m_spec.width, pixelsize, - &encoded[eoffset], length); + make_span(encoded).subspan(eoffset)); if (!e) return false; eoffset += e; diff --git a/testsuite/rla/ref/out.txt b/testsuite/rla/ref/out.txt index ea5780a022..6e79e9dfc2 100644 --- a/testsuite/rla/ref/out.txt +++ b/testsuite/rla/ref/out.txt @@ -322,5 +322,11 @@ Full command line was: oiiotool ERROR: read : "src/crash-1.rla": rla image full/display resolution must be at least 1x1, but the file specified -281x18999x1. Possible corrupt input? Full command line was: > oiiotool src/crash-1.rla -o crash5.exr +oiiotool ERROR: read : "src/crash-5152.rla": Read error: malformed RLE record +Full command line was: +> oiiotool src/crash-5152.rla -o crash6.exr +oiiotool ERROR: read : "src/crash-5159.rla": Read error: couldn't read RLE data span +Full command line was: +> oiiotool src/crash-5159.rla -o crash7.exr Comparing "rlacrop.rla" and "ref/rlacrop.rla" PASS diff --git a/testsuite/rla/run.py b/testsuite/rla/run.py index c2b74eb0d6..e756620863 100755 --- a/testsuite/rla/run.py +++ b/testsuite/rla/run.py @@ -23,5 +23,7 @@ command += oiiotool("src/crash-1629.rla -o crash3.exr", failureok = True) command += oiiotool("src/crash-3951.rla -o crash4.exr", failureok = True) command += oiiotool("src/crash-1.rla -o crash5.exr", failureok = True) +command += oiiotool("src/crash-5152.rla -o crash6.exr", failureok = True) +command += oiiotool("src/crash-5159.rla -o crash7.exr", failureok = True) outputs = [ "rlacrop.rla", 'out.txt' ] diff --git a/testsuite/rla/src/crash-5152.rla b/testsuite/rla/src/crash-5152.rla new file mode 100644 index 0000000000..7af4af88df Binary files /dev/null and b/testsuite/rla/src/crash-5152.rla differ diff --git a/testsuite/rla/src/crash-5159.rla b/testsuite/rla/src/crash-5159.rla new file mode 100644 index 0000000000..77e82155c1 Binary files /dev/null and b/testsuite/rla/src/crash-5159.rla differ