Backport of changes from 2.x branch to fix CVE-2009-2294 The vulnerability is triggered by HTML pages with embedded PNG images, the Png_datainfo_callback function does not properly validate the width and height of the image. Specific PNG images with large width and height can be crafted to trigger the vulnerability. http://www.ocert.org/advisories/ocert-2009-008.html http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-2294 --- src/gif.c +++ src/gif.c @@ -848,6 +848,16 @@ static size_t Gif_do_img_desc(DilloGif *gif, void *Buf, gif->Width = LM_to_uint(buf[4], buf[5]); gif->Height = LM_to_uint(buf[6], buf[7]); + + /* check max image size */ + if (gif->Width <= 0 || gif->Height <= 0 || + gif->Width > IMAGE_MAX_AREA / gif->Height) { + DEBUG_MSG(5, "Gif_do_img_desc: suspicious image size request %ux%u\n", + gif->Width, gif->Height); + gif->state = 999; + return 0; + } + gif->linebuf = g_malloc(gif->Width); a_Dicache_set_parms(gif->url, gif->version, gif->Image, --- src/html.c +++ src/html.c @@ -2459,8 +2459,6 @@ static DilloImage *Html_add_new_image(DilloHtml *html, char *tag, gint tagsize, DwStyle *style_attrs, gboolean add) { - const int MAX_W = 6000, MAX_H = 6000; - DilloImage *Image; char *width_ptr, *height_ptr, *alt_ptr; const char *attrbuf; @@ -2484,7 +2482,14 @@ static DilloImage *Html_add_new_image(DilloHtml *html, char *tag, s_h = Html_parse_length (html, height_ptr); h = (DW_STYLE_IS_ABS_LENGTH(s_h)) ? DW_STYLE_ABS_LENGTH_VAL(s_h) : 0; } - if (w < 0 || h < 0 || abs(w*h) > MAX_W * MAX_H) { + /* Check for suspicious image size request that would cause + * an excessive amount of memory to be allocated for the + * image buffer. + * Be careful to avoid integer overflows during the checks. + */ + if (w < 0 || h < 0 || + w > IMAGE_MAX_AREA || h > IMAGE_MAX_AREA || + (h > 0 && w > IMAGE_MAX_AREA / h)) { g_free(width_ptr); g_free(height_ptr); width_ptr = height_ptr = NULL; --- src/image.h +++ src/image.h @@ -8,6 +8,16 @@ #include "dw_image.h" #include "bitvec.h" +/* + * Defines + */ + +/* Arbitrary maximum for image size (to avoid image size-crafting attacks). */ +#define IMAGE_MAX_AREA (6000 * 6000) + +/* + * Types + */ typedef struct _DilloImage DilloImage; --- src/jpeg.c +++ src/jpeg.c @@ -287,6 +287,17 @@ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, guint BufSize) else DEBUG_MSG(5, "jpeg: can't handle %d component images\n", jpeg->cinfo.num_components); + + /* check max image size */ + if (jpeg->cinfo.image_width <= 0 || jpeg->cinfo.image_height <= 0 || + jpeg->cinfo.image_width > IMAGE_MAX_AREA / jpeg->cinfo.image_height) { + DEBUG_MSG(5, "Jpeg_write: suspicious image size request %ux%u\n", + jpeg->cinfo.image_width, + jpeg->cinfo.image_height); + jpeg->state = DILLO_JPEG_ERROR; + return; + } + a_Dicache_set_parms(jpeg->url, jpeg->version, jpeg->Image, (guint)jpeg->cinfo.image_width, (guint)jpeg->cinfo.image_height, --- src/png.c +++ src/png.c @@ -147,6 +147,15 @@ Png_datainfo_callback(png_structp png_ptr, png_infop info_ptr) png_get_IHDR(png_ptr, info_ptr, &png->width, &png->height, &bit_depth, &color_type, &interlace_type, NULL, NULL); + /* check max image size */ + if (png->width <= 0 || png->height <= 0 || + png->width > IMAGE_MAX_AREA / png->height) { + DEBUG_MSG(5, "Png_datainfo_callback: suspicious image size request %ldx%ld\n", + png->width, png->height); + Png_error_handling(png_ptr, "Aborting..."); + return; /* not reached */ + } + DEBUG_MSG(5, "Png_datainfo_callback: png->width = %ld\n" "Png_datainfo_callback: png->height = %ld\n", png->width, png->height);