imageio/tiff: Return error before allocating bad tile size

Change-Id: I5820b808e25beeda0fd4e755b62da0caabe48d8d
This commit is contained in:
Yannis Guyon 2019-10-15 10:44:17 +02:00
parent af650c0bd2
commit 853ea3d846

View File

@ -156,7 +156,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
Metadata* const metadata) { Metadata* const metadata) {
MyData my_data = { data, (toff_t)data_size, 0 }; MyData my_data = { data, (toff_t)data_size, 0 };
TIFF* tif; TIFF* tif;
uint32_t width, height; uint32_t image_width, image_height, tile_width, tile_height;
uint16_t samples_per_px = 0; uint16_t samples_per_px = 0;
uint16_t extra_samples = 0; uint16_t extra_samples = 0;
uint16_t* extra_samples_ptr = NULL; uint16_t* extra_samples_ptr = NULL;
@ -189,15 +189,25 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
} }
if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) && if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) &&
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) { TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) {
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n"); fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
goto End; goto End;
} }
if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)width * height, if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)image_width * image_height,
sizeof(*raster))) { sizeof(*raster))) {
goto End; goto End;
} }
// According to spec, a tile can be bigger than the image. However it should
// be a multiple of 16 and not way too large, so check that it's not more than
// twice the image size, for dimensions above some arbitrary minimum 32.
if ((TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) &&
tile_width > 32 && tile_width / 2 > image_width) ||
(TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height) &&
tile_height > 32 && tile_height / 2 > image_height)) {
fprintf(stderr, "Error! TIFF tile dimensions are too big.\n");
goto End;
}
if (samples_per_px > 3 && !TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, if (samples_per_px > 3 && !TIFFGetField(tif, TIFFTAG_EXTRASAMPLES,
&extra_samples, &extra_samples_ptr)) { &extra_samples, &extra_samples_ptr)) {
fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n"); fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n");
@ -205,27 +215,28 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
} }
// _Tiffmalloc uses a signed type for size. // _Tiffmalloc uses a signed type for size.
alloc_size = (int64_t)((uint64_t)width * height * sizeof(*raster)); alloc_size =
(int64_t)((uint64_t)image_width * image_height * sizeof(*raster));
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End; if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
raster = (uint32*)_TIFFmalloc((tsize_t)alloc_size); raster = (uint32*)_TIFFmalloc((tsize_t)alloc_size);
if (raster != NULL) { if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, width, height, raster, if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster,
ORIENTATION_TOPLEFT, 1)) { ORIENTATION_TOPLEFT, 1)) {
const int stride = width * sizeof(*raster); const int stride = image_width * sizeof(*raster);
pic->width = width; pic->width = image_width;
pic->height = height; pic->height = image_height;
// TIFF data is ABGR // TIFF data is ABGR
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
TIFFSwabArrayOfLong(raster, width * height); TIFFSwabArrayOfLong(raster, image_width * image_height);
#endif #endif
// if we have an alpha channel, we must un-multiply from rgbA to RGBA // if we have an alpha channel, we must un-multiply from rgbA to RGBA
if (extra_samples == 1 && extra_samples_ptr != NULL && if (extra_samples == 1 && extra_samples_ptr != NULL &&
extra_samples_ptr[0] == EXTRASAMPLE_ASSOCALPHA) { extra_samples_ptr[0] == EXTRASAMPLE_ASSOCALPHA) {
uint32_t y; uint32_t y;
uint8_t* tmp = (uint8_t*)raster; uint8_t* tmp = (uint8_t*)raster;
for (y = 0; y < height; ++y) { for (y = 0; y < image_height; ++y) {
MultARGBRow(tmp, width); MultARGBRow(tmp, image_width);
tmp += stride; tmp += stride;
} }
} }