Skip to content

Commit 7d16832

Browse files
authored
fix(tiff): check for invalid bit depth for palette images (#5091)
Reading the TIFF 6.0 spec, on p. 23, it sure looks like palette images can only be 4 or 8 bits per sample. But the libtiff set of test images indeed has 2, 4, 8, and yes, 16 bps palette images among the examples. So I think we should support up to 16, since we might encounter it in the wild, but no higher. We didn't previously check for this, though, and that could lead to accepting invalid TIFF files, and then potentially have problems with `(1 << m_bitspersample)` which appears several times. That of course is safe if m_bitspersample can't be > 16. Also check and proper error for a file that has a bitspersample that is not one of the valid choices (1, 2, 4, 6, 8, 10, 12, 14, 16, 24, 32, 64), and proper errors for if the sampleformat was an unknown value or was not a valid value for the number of bits per sample. Note that this changes the reference output of some tests because the new checks can alter the first error discovered in a corrupt file. Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent 8abf94e commit 7d16832

7 files changed

Lines changed: 32 additions & 15 deletions

File tree

src/tiff.imageio/tiffinput.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,10 @@ class TIFFInput final : public ImageInput {
238238
// like we think the file is hopelessly corrupted.
239239
bool readspec(bool read_meta = true);
240240

241-
// Figure out all the photometric-related aspects of the header
242-
void readspec_photometric();
241+
// Figure out all the photometric-related aspects of the header.
242+
// Return true if all is fine, false if something really bad happens,
243+
// like we think the file is invalid or hopelessly corrupted.
244+
bool readspec_photometric();
243245

244246
// Convert planar separate to contiguous data format
245247
void separate_to_contig(size_t nplanes, size_t nvals,
@@ -1205,6 +1207,7 @@ TIFFInput::readspec(bool read_meta)
12051207
TIFFGetFieldDefaulted(m_tif, TIFFTAG_BITSPERSAMPLE, &m_bitspersample);
12061208
m_spec.attribute("oiio:BitsPerSample", (int)m_bitspersample);
12071209

1210+
m_spec.set_format(TypeDesc::UNKNOWN);
12081211
unsigned short sampleformat = SAMPLEFORMAT_UINT;
12091212
TIFFGetFieldDefaulted(m_tif, TIFFTAG_SAMPLEFORMAT, &sampleformat);
12101213
switch (m_bitspersample) {
@@ -1233,8 +1236,7 @@ TIFFInput::readspec(bool read_meta)
12331236
else if (sampleformat == SAMPLEFORMAT_IEEEFP) {
12341237
m_spec.set_format(TypeDesc::HALF);
12351238
// Adobe extension, see http://chriscox.org/TIFFTN3d1.pdf
1236-
} else
1237-
m_spec.set_format(TypeDesc::UNKNOWN);
1239+
}
12381240
break;
12391241
case 24:
12401242
// Make 24 bit look like 32 bit
@@ -1245,16 +1247,22 @@ TIFFInput::readspec(bool read_meta)
12451247
m_spec.set_format(TypeDesc::UINT32);
12461248
else if (sampleformat == SAMPLEFORMAT_INT)
12471249
m_spec.set_format(TypeDesc::INT32);
1248-
else
1249-
m_spec.set_format(TypeDesc::UNKNOWN);
12501250
break;
12511251
case 64:
12521252
if (sampleformat == SAMPLEFORMAT_IEEEFP)
12531253
m_spec.set_format(TypeDesc::DOUBLE);
12541254
else
12551255
m_spec.set_format(TypeDesc::UNKNOWN);
12561256
break;
1257-
default: m_spec.set_format(TypeDesc::UNKNOWN); break;
1257+
default:
1258+
errorfmt("Invalid bits per sample ({})", m_bitspersample);
1259+
return false;
1260+
}
1261+
1262+
if (m_spec.format == TypeUnknown) {
1263+
errorfmt("Invalid sampleformat value ({}) for {} bits per sample",
1264+
sampleformat, m_bitspersample);
1265+
return false;
12581266
}
12591267

12601268
// Use the table for all the obvious things that can be mindlessly
@@ -1278,7 +1286,8 @@ TIFFInput::readspec(bool read_meta)
12781286
TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &m_photometric);
12791287
m_spec.attribute("tiff:PhotometricInterpretation", (int)m_photometric);
12801288

1281-
readspec_photometric();
1289+
if (!readspec_photometric())
1290+
return false;
12821291

12831292
TIFFGetFieldDefaulted(m_tif, TIFFTAG_PLANARCONFIG, &m_planarconfig);
12841293
m_separate = (m_planarconfig == PLANARCONFIG_SEPARATE
@@ -1579,7 +1588,7 @@ TIFFInput::readspec(bool read_meta)
15791588

15801589

15811590

1582-
void
1591+
bool
15831592
TIFFInput::readspec_photometric()
15841593
{
15851594
switch (m_photometric) {
@@ -1651,6 +1660,12 @@ TIFFInput::readspec_photometric()
16511660
m_spec.attribute("tiff:ColorSpace", "LOGLUV");
16521661
break;
16531662
case PHOTOMETRIC_PALETTE: {
1663+
if (m_bitspersample > 16) {
1664+
errorfmt(
1665+
"Palette images only support <= 16 bits per sample (was {})",
1666+
m_bitspersample);
1667+
return false;
1668+
}
16541669
m_spec.attribute("tiff:ColorSpace", "palette");
16551670
// Read the color map
16561671
unsigned short *r = NULL, *g = NULL, *b = NULL;
@@ -1710,6 +1725,8 @@ TIFFInput::readspec_photometric()
17101725
m_spec.attribute("oiio:ColorSpace",
17111726
m_spec.get_string_attribute("tiff:ColorSpace"));
17121727
}
1728+
1729+
return true;
17131730
}
17141731

17151732

testsuite/tiff-misc/ref/out-libtiff409.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ src/separate.tif : 128 x 128, 3 channel, uint8 tiff
1414
tiff:RowsPerStrip: 7
1515
Comparing "src/separate.tif" and "separate.tif"
1616
PASS
17-
oiiotool ERROR: read : No support for data format of "src/corrupt1.tif"
17+
oiiotool ERROR: read : "src/corrupt1.tif": Invalid bits per sample (5)
1818
Full command line was:
1919
> oiiotool --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif
2020
oiiotool ERROR: read : File does not exist: "src/crash-1633.tif"

testsuite/tiff-misc/ref/out-libtiff410.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ src/separate.tif : 128 x 128, 3 channel, uint8 tiff
1414
tiff:RowsPerStrip: 7
1515
Comparing "src/separate.tif" and "separate.tif"
1616
PASS
17-
oiiotool ERROR: read : No support for data format of "src/corrupt1.tif"
17+
oiiotool ERROR: read : "src/corrupt1.tif": Invalid bits per sample (5)
1818
Full command line was:
1919
> oiiotool --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif
2020
oiiotool ERROR: read : File does not exist: "src/crash-1633.tif"

testsuite/tiff-misc/ref/out-libtiff430.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ src/separate.tif : 128 x 128, 3 channel, uint8 tiff
1414
tiff:RowsPerStrip: 7
1515
Comparing "src/separate.tif" and "separate.tif"
1616
PASS
17-
oiiotool ERROR: read : No support for data format of "src/corrupt1.tif"
17+
oiiotool ERROR: read : "src/corrupt1.tif": Invalid bits per sample (5)
1818
Full command line was:
1919
> oiiotool --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif
2020
oiiotool ERROR: read : File does not exist: "src/crash-1633.tif"

testsuite/tiff-misc/ref/out-libtiff470-b.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ src/separate.tif : 128 x 128, 3 channel, uint8 tiff
1414
tiff:RowsPerStrip: 7
1515
Comparing "src/separate.tif" and "separate.tif"
1616
PASS
17-
oiiotool ERROR: read : No support for data format of "src/corrupt1.tif"
17+
oiiotool ERROR: read : "src/corrupt1.tif": Invalid bits per sample (5)
1818
Full command line was:
1919
> oiiotool --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif
2020
oiiotool ERROR: read : File does not exist: "src/crash-1633.tif"

testsuite/tiff-misc/ref/out-libtiff470.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ src/separate.tif : 128 x 128, 3 channel, uint8 tiff
1414
tiff:RowsPerStrip: 7
1515
Comparing "src/separate.tif" and "separate.tif"
1616
PASS
17-
oiiotool ERROR: read : No support for data format of "src/corrupt1.tif"
17+
oiiotool ERROR: read : "src/corrupt1.tif": Invalid bits per sample (5)
1818
Full command line was:
1919
> oiiotool --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif
2020
oiiotool ERROR: read : File does not exist: "src/crash-1633.tif"

testsuite/tiff-misc/ref/out.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ src/separate.tif : 128 x 128, 3 channel, uint8 tiff
1414
tiff:RowsPerStrip: 7
1515
Comparing "src/separate.tif" and "separate.tif"
1616
PASS
17-
oiiotool ERROR: read : No support for data format of "src/corrupt1.tif"
17+
oiiotool ERROR: read : "src/corrupt1.tif": Invalid bits per sample (5)
1818
Full command line was:
1919
> oiiotool --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif
2020
oiiotool ERROR: read : File does not exist: "src/crash-1633.tif"

0 commit comments

Comments
 (0)