Skip to content

Commit

Permalink
TIFF: guard against buffer overflow for certain CMYK files (AcademySo…
Browse files Browse the repository at this point in the history
  • Loading branch information
lgritz committed Oct 24, 2022
1 parent 5bfe48a commit 5563449
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 8 deletions.
20 changes: 13 additions & 7 deletions src/tiff.imageio/tiffinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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<unsigned char> scratch2(m_separate ? m_spec.tile_bytes()
: 0);
// Where to read? Directly into user data if no channel shuffling
Expand Down
Binary file added testsuite/tiff-misc/crash-1633.tif
Binary file not shown.
Binary file added testsuite/tiff-misc/crash-1643.tif
Binary file not shown.
6 changes: 6 additions & 0 deletions testsuite/tiff-misc/ref/out-libtiff403.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions testsuite/tiff-misc/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 3 additions & 1 deletion testsuite/tiff-misc/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -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" ]

0 comments on commit 5563449

Please sign in to comment.