diff -rupN --no-dereference Pillow-5.4.1/src/libImaging/TiffDecode.c Pillow-5.4.1-new/src/libImaging/TiffDecode.c --- Pillow-5.4.1/src/libImaging/TiffDecode.c 2019-01-06 13:12:16.000000000 +0100 +++ Pillow-5.4.1-new/src/libImaging/TiffDecode.c 2020-02-13 14:44:21.697014248 +0100 @@ -243,20 +243,26 @@ int ImagingLibTiffDecode(Imaging im, Ima } if (TIFFIsTiled(tiff)) { - uint32 x, y, tile_y; + uint32 x, y, tile_y, row_byte_size; uint32 tileWidth, tileLength; UINT8 *new_data; - state->bytes = TIFFTileSize(tiff); + TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth); + TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength); + + // We could use TIFFTileSize, but for YCbCr data it returns subsampled data size + row_byte_size = (tileWidth * state->bits + 7) / 8; - /* overflow check for malloc */ - if (state->bytes > INT_MAX - 1) { + /* overflow check for realloc */ + if (INT_MAX / row_byte_size < tileLength) { state->errcode = IMAGING_CODEC_MEMORY; TIFFClose(tiff); return -1; } - /* realloc to fit whole tile */ + state->bytes = row_byte_size * tileLength; + + /* malloc check above */ new_data = realloc (state->buffer, state->bytes); if (!new_data) { state->errcode = IMAGING_CODEC_MEMORY; @@ -268,8 +274,6 @@ int ImagingLibTiffDecode(Imaging im, Ima TRACE(("TIFFTileSize: %d\n", state->bytes)); - TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth); - TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength); for (y = state->yoff; y < state->ysize; y += tileLength) { for (x = state->xoff; x < state->xsize; x += tileWidth) { diff -rupN --no-dereference Pillow-5.4.1/Tests/test_file_libtiff.py Pillow-5.4.1-new/Tests/test_file_libtiff.py --- Pillow-5.4.1/Tests/test_file_libtiff.py 2019-01-06 13:12:16.000000000 +0100 +++ Pillow-5.4.1-new/Tests/test_file_libtiff.py 2020-02-13 14:44:21.697014248 +0100 @@ -701,6 +701,15 @@ class TestFileLibTiff(LibTiffTestCase): self.assert_image_similar_tofile(im, "Tests/images/flower.jpg", 0.5) + def test_realloc_overflow(self): + TiffImagePlugin.READ_LIBTIFF = True + with Image.open("Tests/images/tiff_overflow_rows_per_strip.tif") as im: + with self.assertRaises(IOError) as e: + im.load() + + # Assert that the error code is IMAGING_CODEC_MEMORY + self.assertEqual(str(e.exception), "-9") + TiffImagePlugin.READ_LIBTIFF = False if __name__ == '__main__': unittest.main()