Skip to content

Commit 19c4563

Browse files
authored
fix(bmp): Correctly handle the combination of greyscale + RLE compression (#5163)
Fixes #5158 Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent caa5174 commit 19c4563

4 files changed

Lines changed: 38 additions & 7 deletions

File tree

src/bmp.imageio/bmpinput.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -395,13 +395,28 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
395395
if ((m_dib_header.compression == RLE4_COMPRESSION
396396
|| m_dib_header.compression == RLE8_COMPRESSION)
397397
&& m_colortable.size()) {
398-
for (int x = 0; x < m_spec.width; ++x) {
399-
int p = m_uncompressed[int64_t(m_spec.height - 1 - y) * m_spec.width
400-
+ x];
401-
auto& c = colortable(p);
402-
mscanline[3 * x] = c.r;
403-
mscanline[3 * x + 1] = c.g;
404-
mscanline[3 * x + 2] = c.b;
398+
if (m_spec.nchannels == 1) {
399+
OIIO_CONTRACT_ASSERT(m_allgray);
400+
for (int x = 0; x < m_spec.width; ++x) {
401+
int p
402+
= m_uncompressed[int64_t(m_spec.height - 1 - y) * m_spec.width
403+
+ x];
404+
auto& c = colortable(p);
405+
mscanline[x] = c.r;
406+
// For the "all gray" case, rgb are equal and we're filling in
407+
// a 1-channel data buffer.
408+
}
409+
} else {
410+
OIIO_CONTRACT_ASSERT(m_spec.nchannels == 3);
411+
for (int x = 0; x < m_spec.width; ++x) {
412+
int p
413+
= m_uncompressed[int64_t(m_spec.height - 1 - y) * m_spec.width
414+
+ x];
415+
auto& c = colortable(p);
416+
mscanline[3 * x] = c.r;
417+
mscanline[3 * x + 1] = c.g;
418+
mscanline[3 * x + 2] = c.b;
419+
}
405420
}
406421
return true;
407422
}

testsuite/bmp/ref/out.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,17 @@ Reading ../oiio-images/bmp/gracehopper.bmp
291291
oiio:ColorSpace: "srgb_rec709_scene"
292292
Comparing "../oiio-images/bmp/gracehopper.bmp" and "gracehopper.bmp"
293293
PASS
294+
Reading src/crash-5158.bmp
295+
src/crash-5158.bmp : 13 x 32, 1 channel, uint8 bmp
296+
SHA-1: 5BAB75849B9D716B8FEC896E7B0F2D37659B3BAD
297+
channel list: Y
298+
compression: "rle8"
299+
ResolutionUnit: "m"
300+
XResolution: 1179648
301+
YResolution: 32
302+
bmp:bitsperpixel: 8
303+
bmp:version: 3
304+
oiio:ColorSpace: "srgb_rec709_scene"
294305
oiiotool ERROR: read : "src/decodecolormap-corrupt.bmp": Possible corrupted header, invalid palette size
295306
Full command line was:
296307
> oiiotool --info -v -a --hash src/decodecolormap-corrupt.bmp

testsuite/bmp/run.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
# Test BMP of the 56-byte DIB header variety
3131
command += rw_command ("../oiio-images/bmp", "gracehopper.bmp")
3232

33+
# Regression test for RLE8 heap buffer overflow when palette is all-gray
34+
# (detected as 1-channel, but RLE path was writing 3 bytes per pixel).
35+
# See https://github.com/AcademySoftwareFoundation/OpenImageIO/issues/5158
36+
command += info_command ("src/crash-5158.bmp", hash=1)
37+
3338
# See if we handle these corrupt files with useful error messages
3439
command += info_command ("src/decodecolormap-corrupt.bmp")
3540
command += info_command ("src/bad-y.bmp")

testsuite/bmp/src/crash-5158.bmp

905 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)