mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-19 20:08:28 +01:00
TiffDec: enforce stricter mem/dimension limit on tiles
Tile can be even larger than image dimensions. Change-Id: I80518e815bb11d7a07c8189d0493b3cc60e29815
This commit is contained in:
parent
8696147da4
commit
289757fe1e
@ -148,9 +148,11 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
|
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height) {
|
||||||
const uint64_t total_size = nmemb * size;
|
const uint64_t total_size = stride * height;
|
||||||
int ok = (total_size == (size_t)total_size);
|
int ok = (total_size == (size_t)total_size);
|
||||||
|
// check that 'stride' is representable as int:
|
||||||
|
ok = ok && ((uint64_t)(int)stride == stride);
|
||||||
#if defined(WEBP_MAX_IMAGE_SIZE)
|
#if defined(WEBP_MAX_IMAGE_SIZE)
|
||||||
ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE);
|
ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,8 +54,8 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Returns 0 in case of overflow of nmemb * size.
|
// Returns 0 in case of overflow, memory over-allocation or excessive dimension.
|
||||||
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size);
|
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
@ -157,6 +157,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
MyData my_data = { data, (toff_t)data_size, 0 };
|
MyData my_data = { data, (toff_t)data_size, 0 };
|
||||||
TIFF* tif;
|
TIFF* tif;
|
||||||
uint32_t image_width, image_height, tile_width, tile_height;
|
uint32_t image_width, image_height, tile_width, tile_height;
|
||||||
|
uint64_t stride;
|
||||||
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;
|
||||||
@ -194,20 +195,31 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
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)image_width * image_height,
|
stride = (uint64_t)image_width * sizeof(*raster);
|
||||||
sizeof(*raster))) {
|
if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, image_height)) {
|
||||||
|
fprintf(stderr, "Error! TIFF image dimension (%d x %d) is too large.\n",
|
||||||
|
image_width, image_height);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
// According to spec, a tile can be bigger than the image. However it should
|
// 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
|
// be a multiple of 16 and not way too large, so check that it's not more
|
||||||
// twice the image size, for dimensions above some arbitrary minimum 32.
|
// than twice the image size, for dimensions above some arbitrary minimum
|
||||||
if ((TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) &&
|
// 32. We also check that they respect WebP's dimension and memory limit.
|
||||||
tile_width > 32 && tile_width / 2 > image_width) ||
|
// Note that a tile can be 6byte/px in some cases. Here we assume
|
||||||
(TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height) &&
|
// 4byte/px with sizeof(*raster), to be conservative.
|
||||||
tile_height > 32 && tile_height / 2 > image_height)) {
|
if (TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) &&
|
||||||
fprintf(stderr, "Error! TIFF tile dimensions are too big.\n");
|
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) {
|
||||||
|
if ((tile_width > 32 && tile_width / 2 > image_width) ||
|
||||||
|
(tile_height > 32 && tile_height / 2 > image_height) ||
|
||||||
|
ImgIoUtilCheckSizeArgumentsOverflow(
|
||||||
|
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
|
||||||
|
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
|
||||||
|
tile_width, tile_height);
|
||||||
goto End;
|
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");
|
||||||
@ -215,15 +227,13 @@ 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 =
|
alloc_size = (int64_t)(stride * image_height);
|
||||||
(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, image_width, image_height, raster,
|
if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster,
|
||||||
ORIENTATION_TOPLEFT, 1)) {
|
ORIENTATION_TOPLEFT, 1)) {
|
||||||
const int stride = image_width * sizeof(*raster);
|
|
||||||
pic->width = image_width;
|
pic->width = image_width;
|
||||||
pic->height = image_height;
|
pic->height = image_height;
|
||||||
// TIFF data is ABGR
|
// TIFF data is ABGR
|
||||||
@ -241,8 +251,8 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok = keep_alpha
|
ok = keep_alpha
|
||||||
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
|
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride)
|
||||||
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
|
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride);
|
||||||
}
|
}
|
||||||
_TIFFfree(raster);
|
_TIFFfree(raster);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user