mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
imageio_util: add ImgIoUtilCheckSizeArgumentsOverflow
and use it to validate decoder allocations. fixes a crash in jpegdec at least. BUG=webp:312 Change-Id: Ia940590098f29510add6aad10a8dfe9e9ea46bf4
This commit is contained in:
parent
68ae5b671f
commit
bc86b7a8a1
@ -134,3 +134,10 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
|
||||||
|
const uint64_t total_size = nmemb * size;
|
||||||
|
return (total_size == (size_t)total_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -49,6 +49,11 @@ int ImgIoUtilWriteFile(const char* const file_name,
|
|||||||
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||||
uint8_t* dst, int dst_stride, int width, int height);
|
uint8_t* dst, int dst_stride, int width, int height);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Returns 0 in case of overflow of nmemb * size.
|
||||||
|
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
|
#include "./imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -257,7 +258,8 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
WebPPicture* const pic, int keep_alpha,
|
WebPPicture* const pic, int keep_alpha,
|
||||||
Metadata* const metadata) {
|
Metadata* const metadata) {
|
||||||
volatile int ok = 0;
|
volatile int ok = 0;
|
||||||
int stride, width, height;
|
int width, height;
|
||||||
|
int64_t stride;
|
||||||
volatile struct jpeg_decompress_struct dinfo;
|
volatile struct jpeg_decompress_struct dinfo;
|
||||||
struct my_error_mgr jerr;
|
struct my_error_mgr jerr;
|
||||||
uint8_t* volatile rgb = NULL;
|
uint8_t* volatile rgb = NULL;
|
||||||
@ -296,9 +298,14 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
width = dinfo.output_width;
|
width = dinfo.output_width;
|
||||||
height = dinfo.output_height;
|
height = dinfo.output_height;
|
||||||
stride = dinfo.output_width * dinfo.output_components * sizeof(*rgb);
|
stride = (int64_t)dinfo.output_width * dinfo.output_components * sizeof(*rgb);
|
||||||
|
|
||||||
rgb = (uint8_t*)malloc(stride * height);
|
if (stride != (int)stride ||
|
||||||
|
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb = (uint8_t*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL) {
|
if (rgb == NULL) {
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
@ -325,7 +332,7 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
// WebP conversion.
|
// WebP conversion.
|
||||||
pic->width = width;
|
pic->width = width;
|
||||||
pic->height = height;
|
pic->height = height;
|
||||||
ok = WebPPictureImportRGB(pic, rgb, stride);
|
ok = WebPPictureImportRGB(pic, rgb, (int)stride);
|
||||||
if (!ok) goto Error;
|
if (!ok) goto Error;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
|
#include "./imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
||||||
@ -216,7 +217,7 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
int p;
|
int p;
|
||||||
volatile int ok = 0;
|
volatile int ok = 0;
|
||||||
png_uint_32 width, height, y;
|
png_uint_32 width, height, y;
|
||||||
png_uint_32 stride;
|
int64_t stride;
|
||||||
uint8_t* volatile rgb = NULL;
|
uint8_t* volatile rgb = NULL;
|
||||||
|
|
||||||
context.data = data;
|
context.data = data;
|
||||||
@ -269,8 +270,14 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
num_passes = png_set_interlace_handling(png);
|
num_passes = png_set_interlace_handling(png);
|
||||||
png_read_update_info(png, info);
|
png_read_update_info(png, info);
|
||||||
stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
|
|
||||||
rgb = (uint8_t*)malloc(stride * height);
|
stride = (int64_t)(has_alpha ? 4 : 3) * width * sizeof(*rgb);
|
||||||
|
if (stride != (int)stride ||
|
||||||
|
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb = (uint8_t*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL) goto Error;
|
if (rgb == NULL) goto Error;
|
||||||
for (p = 0; p < num_passes; ++p) {
|
for (p = 0; p < num_passes; ++p) {
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <tiffio.h>
|
#include <tiffio.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
|
#include "./imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
@ -124,6 +125,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
MySize, MyMapFile, MyUnmapFile);
|
MySize, MyMapFile, MyUnmapFile);
|
||||||
uint32 width, height;
|
uint32 width, height;
|
||||||
uint32* raster;
|
uint32* raster;
|
||||||
|
int64_t alloc_size;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
tdir_t dircount;
|
tdir_t dircount;
|
||||||
|
|
||||||
@ -144,7 +146,16 @@ 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;
|
||||||
}
|
}
|
||||||
raster = (uint32*)_TIFFmalloc(width * height * sizeof(*raster));
|
|
||||||
|
if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)width * height,
|
||||||
|
sizeof(*raster))) {
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
// _Tiffmalloc uses a signed type for size.
|
||||||
|
alloc_size = (int64_t)((uint64_t)width * height * sizeof(*raster));
|
||||||
|
if (alloc_size < 0 || alloc_size != (tmsize_t)alloc_size) goto End;
|
||||||
|
|
||||||
|
raster = (uint32*)_TIFFmalloc((tmsize_t)alloc_size);
|
||||||
if (raster != NULL) {
|
if (raster != NULL) {
|
||||||
if (TIFFReadRGBAImageOriented(tif, width, height, raster,
|
if (TIFFReadRGBAImageOriented(tif, width, height, raster,
|
||||||
ORIENTATION_TOPLEFT, 1)) {
|
ORIENTATION_TOPLEFT, 1)) {
|
||||||
|
@ -274,7 +274,7 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
int has_alpha = 0;
|
int has_alpha = 0;
|
||||||
int stride;
|
int64_t stride;
|
||||||
|
|
||||||
IFS(CoInitialize(NULL));
|
IFS(CoInitialize(NULL));
|
||||||
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
||||||
@ -334,14 +334,19 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
|
|
||||||
// Decode.
|
// Decode.
|
||||||
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
||||||
stride = importer->bytes_per_pixel * width * sizeof(*rgb);
|
stride = (int64_t)importer->bytes_per_pixel * width * sizeof(*rgb);
|
||||||
|
if (stride != (int)stride ||
|
||||||
|
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
rgb = (BYTE*)malloc(stride * height);
|
rgb = (BYTE*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL)
|
if (rgb == NULL)
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
IFS(IWICFormatConverter_CopyPixels(converter, NULL,
|
IFS(IWICFormatConverter_CopyPixels(converter, NULL,
|
||||||
stride, stride * height, rgb));
|
(UINT)stride, (UINT)stride * height, rgb));
|
||||||
|
|
||||||
// WebP conversion.
|
// WebP conversion.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
@ -349,7 +354,7 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
pic->width = width;
|
pic->width = width;
|
||||||
pic->height = height;
|
pic->height = height;
|
||||||
pic->use_argb = 1; // For WIC, we always force to argb
|
pic->use_argb = 1; // For WIC, we always force to argb
|
||||||
ok = importer->import(pic, rgb, stride);
|
ok = importer->import(pic, rgb, (int)stride);
|
||||||
if (!ok) hr = E_FAIL;
|
if (!ok) hr = E_FAIL;
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user