From 245fb0fdcfdb31bd736425fe5299df8eef17b4a7 Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Sun, 23 Oct 2022 16:15:07 -0700 Subject: [PATCH] TIFF: guard against buffer overflow for certain CMYK files --- src/tiff.imageio/tiffinput.cpp | 20 +++++++++++++------- testsuite/tiff-misc/crash-1633.tif | Bin 0 -> 2730 bytes testsuite/tiff-misc/crash-1643.tif | Bin 0 -> 7481 bytes testsuite/tiff-misc/ref/out-libtiff403.txt | 6 ++++++ testsuite/tiff-misc/ref/out.txt | 6 ++++++ testsuite/tiff-misc/run.py | 4 +++- 6 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 testsuite/tiff-misc/crash-1633.tif create mode 100644 testsuite/tiff-misc/crash-1643.tif diff --git a/src/tiff.imageio/tiffinput.cpp b/src/tiff.imageio/tiffinput.cpp index f072135300..62bf5398d1 100644 --- a/src/tiff.imageio/tiffinput.cpp +++ b/src/tiff.imageio/tiffinput.cpp @@ -396,7 +396,7 @@ class TIFFInput final : public ImageInput { } } - void uncompress_one_strip(void* compressed_buf, unsigned long csize, + void uncompress_one_strip(const void* compressed_buf, unsigned long csize, void* uncompressed_buf, size_t strip_bytes, int channels, int width, int height, bool* ok) { @@ -1120,7 +1120,13 @@ TIFFInput::readspec(bool read_meta) } } } - if (m_spec.alpha_channel >= 0) { + if (m_photometric == PHOTOMETRIC_SEPARATED) + m_spec.alpha_channel = -1; // ignore alpha in CMYK + if (m_spec.alpha_channel >= 0 + && m_spec.alpha_channel < m_spec.nchannels) { + while (m_spec.channelnames.size() < size_t(m_spec.nchannels)) + m_spec.channelnames.push_back( + Strutil::fmt::format("channel{}", m_spec.nchannels)); m_spec.channelnames[m_spec.alpha_channel] = "A"; // Special case: "R","A" should really be named "Y","A", since // the first channel is luminance, not red. @@ -1972,8 +1978,8 @@ TIFFInput::read_native_tile(int subimage, int miplevel, int x, int y, int z, // We punted and used the RGBA image interface // libtiff has a call to read just one tile as RGBA. So that's all // we need to do, not buffer the whole image. - m_rgbadata.resize(m_spec.tile_pixels() * 4); - bool ok = TIFFReadRGBATile(m_tif, x, y, &m_rgbadata[0]); + m_rgbadata.resize(m_spec.tile_pixels()); + bool ok = TIFFReadRGBATile(m_tif, x, y, m_rgbadata.data()); if (!ok) { errorf("Unknown error trying to read TIFF as RGBA"); return false; @@ -2000,11 +2006,11 @@ TIFFInput::read_native_tile(int subimage, int miplevel, int x, int y, int z, } imagesize_t tile_pixels = m_spec.tile_pixels(); - imagesize_t nvals = tile_pixels * m_spec.nchannels; + imagesize_t nvals = tile_pixels * m_inputchannels; if (m_photometric == PHOTOMETRIC_PALETTE && m_bitspersample > 8) m_scratch.resize(nvals * 2); // special case for 16 bit palette else - m_scratch.resize(m_spec.tile_bytes()); + m_scratch.resize(nvals * m_spec.format.size()); bool no_bit_convert = (m_bitspersample == 8 || m_bitspersample == 16 || m_bitspersample == 32); if (m_photometric == PHOTOMETRIC_PALETTE) { @@ -2021,7 +2027,7 @@ TIFFInput::read_native_tile(int subimage, int miplevel, int x, int y, int z, } else { // Not palette imagesize_t plane_bytes = m_spec.tile_pixels() * m_spec.format.size(); - int planes = m_separate ? m_spec.nchannels : 1; + int planes = m_separate ? m_inputchannels : 1; std::vector scratch2(m_separate ? m_spec.tile_bytes() : 0); // Where to read? Directly into user data if no channel shuffling diff --git a/testsuite/tiff-misc/crash-1633.tif b/testsuite/tiff-misc/crash-1633.tif new file mode 100644 index 0000000000000000000000000000000000000000..ecd2085c1b1e307dec38a35f88b8e8ff2ce3e653 GIT binary patch literal 2730 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 literal 0 HcmV?d00001 diff --git a/testsuite/tiff-misc/ref/out-libtiff403.txt b/testsuite/tiff-misc/ref/out-libtiff403.txt index 0b853126dc..d72197c527 100644 --- a/testsuite/tiff-misc/ref/out-libtiff403.txt +++ b/testsuite/tiff-misc/ref/out-libtiff403.txt @@ -17,5 +17,11 @@ PASS oiiotool ERROR: read : "src/corrupt1.tif": Could not open file: IO error during reading of "StripOffsets" Full command line was: > oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif +oiiotool ERROR: read : File does not exist: "src/crash-1633.tif" +Full command line was: +> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio --oiioattrib try_all_readers 0 --info -v src/crash-1633.tif +oiiotool ERROR: read : File does not exist: "src/crash-1643.tif" +Full command line was: +> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio --oiioattrib try_all_readers 0 --info -v src/crash-1643.tif Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out.txt b/testsuite/tiff-misc/ref/out.txt index 30d4ad1633..e742e7392f 100644 --- a/testsuite/tiff-misc/ref/out.txt +++ b/testsuite/tiff-misc/ref/out.txt @@ -17,5 +17,11 @@ PASS oiiotool ERROR: read : No support for data format of "src/corrupt1.tif" Full command line was: > oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif +oiiotool ERROR: read : File does not exist: "src/crash-1633.tif" +Full command line was: +> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio --oiioattrib try_all_readers 0 --info -v src/crash-1633.tif +oiiotool ERROR: read : File does not exist: "src/crash-1643.tif" +Full command line was: +> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio --oiioattrib try_all_readers 0 --info -v src/crash-1643.tif Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/run.py b/testsuite/tiff-misc/run.py index f04b439dd7..6e3262d510 100755 --- a/testsuite/tiff-misc/run.py +++ b/testsuite/tiff-misc/run.py @@ -14,7 +14,9 @@ # to force compression in order to properly test: command += rw_command ("src", "separate.tif") -# Test bug we had until OIIO 2.4 for this corrupt file +# Test bugs we had until OIIO 2.4 for these corrupt file command += oiiotool ("--oiioattrib try_all_readers 0 --info -v src/corrupt1.tif", failureok = True) +command += oiiotool ("--oiioattrib try_all_readers 0 --info -v src/crash-1633.tif", failureok = True) +command += oiiotool ("--oiioattrib try_all_readers 0 --info -v src/crash-1643.tif", failureok = True) outputs = [ "check1.tif", "out.txt" ]