diff --git a/src/tiff.imageio/tiffinput.cpp b/src/tiff.imageio/tiffinput.cpp index 2a0ccf5ed2..636c4b4547 100644 --- a/src/tiff.imageio/tiffinput.cpp +++ b/src/tiff.imageio/tiffinput.cpp @@ -2048,6 +2048,9 @@ TIFFInput::read_native_scanline_locked(int subimage, int miplevel, int y, } // Handle less-than-full bit depths + bool use_scratch_dest = m_separate + || (m_photometric == PHOTOMETRIC_SEPARATED + && !m_raw_color); if (m_bitspersample < 8) { // m_scratch now holds nvals n-bit values, contig or separate m_scratch2.resize(input_bytes); @@ -2055,7 +2058,7 @@ TIFFInput::read_native_scanline_locked(int subimage, int miplevel, int y, for (int c = 0; c < planes; ++c) /* planes==1 for contig */ bit_convert(m_separate ? m_spec.width : nvals, &m_scratch2[plane_bytes * c], m_bitspersample, - m_separate + use_scratch_dest ? &m_scratch[plane_bytes * c] : (unsigned char*)data.data() + plane_bytes * c, 8); @@ -2066,7 +2069,7 @@ TIFFInput::read_native_scanline_locked(int subimage, int miplevel, int y, for (int c = 0; c < planes; ++c) /* planes==1 for contig */ bit_convert(m_separate ? m_spec.width : nvals, &m_scratch2[plane_bytes * c], m_bitspersample, - m_separate + use_scratch_dest ? &m_scratch[plane_bytes * c] : (unsigned char*)data.data() + plane_bytes * c, 16); @@ -2077,7 +2080,7 @@ TIFFInput::read_native_scanline_locked(int subimage, int miplevel, int y, for (int c = 0; c < planes; ++c) /* planes==1 for contig */ bit_convert(m_separate ? m_spec.width : nvals, &m_scratch2[plane_bytes * c], m_bitspersample, - m_separate + use_scratch_dest ? &m_scratch[plane_bytes * c] : (unsigned char*)data.data() + plane_bytes * c, 32); diff --git a/testsuite/tiff-misc/ref/out-libtiff403-b.txt b/testsuite/tiff-misc/ref/out-libtiff403-b.txt index 8495a831fb..64188cf31d 100644 --- a/testsuite/tiff-misc/ref/out-libtiff403-b.txt +++ b/testsuite/tiff-misc/ref/out-libtiff403-b.txt @@ -41,5 +41,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff403-c.txt b/testsuite/tiff-misc/ref/out-libtiff403-c.txt index bcc10ab221..0add5ff244 100644 --- a/testsuite/tiff-misc/ref/out-libtiff403-c.txt +++ b/testsuite/tiff-misc/ref/out-libtiff403-c.txt @@ -41,5 +41,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff403.txt b/testsuite/tiff-misc/ref/out-libtiff403.txt index 06ddff8181..643ca1b8cf 100644 --- a/testsuite/tiff-misc/ref/out-libtiff403.txt +++ b/testsuite/tiff-misc/ref/out-libtiff403.txt @@ -41,5 +41,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff409.txt b/testsuite/tiff-misc/ref/out-libtiff409.txt index b8f9937118..8cd8867ea7 100644 --- a/testsuite/tiff-misc/ref/out-libtiff409.txt +++ b/testsuite/tiff-misc/ref/out-libtiff409.txt @@ -41,5 +41,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff410.txt b/testsuite/tiff-misc/ref/out-libtiff410.txt index a8247397b4..5f08284b0c 100644 --- a/testsuite/tiff-misc/ref/out-libtiff410.txt +++ b/testsuite/tiff-misc/ref/out-libtiff410.txt @@ -41,5 +41,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff430.txt b/testsuite/tiff-misc/ref/out-libtiff430.txt index 1ba814e913..73d139c156 100644 --- a/testsuite/tiff-misc/ref/out-libtiff430.txt +++ b/testsuite/tiff-misc/ref/out-libtiff430.txt @@ -56,5 +56,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0 +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff470-b.txt b/testsuite/tiff-misc/ref/out-libtiff470-b.txt index 4f9e90b485..6bebe2b474 100644 --- a/testsuite/tiff-misc/ref/out-libtiff470-b.txt +++ b/testsuite/tiff-misc/ref/out-libtiff470-b.txt @@ -56,5 +56,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff470-c.txt b/testsuite/tiff-misc/ref/out-libtiff470-c.txt index 85bc2404f8..61dc38ee9d 100644 --- a/testsuite/tiff-misc/ref/out-libtiff470-c.txt +++ b/testsuite/tiff-misc/ref/out-libtiff470-c.txt @@ -56,5 +56,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/ref/out-libtiff470.txt b/testsuite/tiff-misc/ref/out-libtiff470.txt index c5df0c6b7d..a86c32046d 100644 --- a/testsuite/tiff-misc/ref/out-libtiff470.txt +++ b/testsuite/tiff-misc/ref/out-libtiff470.txt @@ -56,5 +56,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0 +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 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 a067377d67..707d956136 100644 --- a/testsuite/tiff-misc/ref/out.txt +++ b/testsuite/tiff-misc/ref/out.txt @@ -41,5 +41,22 @@ gps.tif : 64 x 64, 3 channel, uint8 tiff tiff:RowsPerStrip: 32 iconvert ERROR copying "src/crash-cmyk-e12b.tif" to "out.tif" : Decoding error at scanline 0, invalid distance too far back +Reading src/crash-cmyk-1bit.tif +src/crash-cmyk-1bit.tif : 73 x 43, 3 channel, uint1 tiff + SHA-1: 7E9169CEC1B8ABD56C3604AAD37761DBD8FE0F2A + channel list: R, G, B + compression: "none" + DocumentName: "flower-separated-contig-08.tif" + Orientation: 1 (normal) + planarconfig: "contig" + ResolutionUnit: "in" + XResolution: 0 + YResolution: 72 + oiio:BitsPerSample: 1 + tiff:ColorSpace: "CMYK" + tiff:Compression: 1 + tiff:PhotometricInterpretation: 5 + tiff:PlanarConfiguration: 1 + tiff:RowsPerStrip: 28 Comparing "check1.tif" and "ref/check1.tif" PASS diff --git a/testsuite/tiff-misc/run.py b/testsuite/tiff-misc/run.py index 04030b4950..434223de79 100755 --- a/testsuite/tiff-misc/run.py +++ b/testsuite/tiff-misc/run.py @@ -32,4 +32,12 @@ # Test bug with corrupt cmyk file command += iconvert ("src/crash-cmyk-e12b.tif out.tif", failureok=True) +# Regression test: CMYK (photometric=separated) TIFF missing its +# BitsPerSample tag, which makes libtiff default it to 1 bit/sample. When +# unpacking the sub-8-bit samples for the CMYK->RGB conversion, the bit +# unpacker was writing all 4 input channels' worth of unpacked samples +# directly into the 3-channel RGB output buffer instead of scratch space, +# causing a heap buffer overflow. +command += info_command ("src/crash-cmyk-1bit.tif", safematch=True) + outputs = [ "check1.tif", "out.txt" ] diff --git a/testsuite/tiff-misc/src/crash-cmyk-1bit.tif b/testsuite/tiff-misc/src/crash-cmyk-1bit.tif new file mode 100644 index 0000000000..531e6c05e9 Binary files /dev/null and b/testsuite/tiff-misc/src/crash-cmyk-1bit.tif differ