CVE-2015-0852 Description: fix integer overflow Origin: upstream http://freeimage.cvs.sourceforge.net/viewvc/freeimage/FreeImage/Source/FreeImage/PluginPCX.cpp?view=patch&r1=1.17&r2=1.18&pathrev=MAIN http://freeimage.cvs.sourceforge.net/viewvc/freeimage/FreeImage/Source/FreeImage/PluginPCX.cpp?view=patch&r1=1.18&r2=1.19&pathrev=MAIN Bug-Debian: https://bugs.debian.org/797165 Last-Update: 2015-09-14 --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ Index: freeimage/Source/FreeImage/PluginPCX.cpp =================================================================== --- freeimage.orig/Source/FreeImage/PluginPCX.cpp +++ Source/FreeImage/PluginPCX.cpp @@ -347,12 +347,14 @@ Load(FreeImageIO *io, fi_handle handle, try { // check PCX identifier - - long start_pos = io->tell_proc(handle); - BOOL validated = pcx_validate(io, handle); - io->seek_proc(handle, start_pos, SEEK_SET); - if(!validated) { - throw FI_MSG_ERROR_MAGIC_NUMBER; + // (note: should have been already validated using FreeImage_GetFileType but check again) + { + long start_pos = io->tell_proc(handle); + BOOL validated = pcx_validate(io, handle); + io->seek_proc(handle, start_pos, SEEK_SET); + if(!validated) { + throw FI_MSG_ERROR_MAGIC_NUMBER; + } } // process the header @@ -366,20 +368,38 @@ Load(FreeImageIO *io, fi_handle handle, SwapHeader(&header); #endif - // allocate a new DIB + // process the window + const WORD *window = header.window; // left, upper, right,lower pixel coord. + const int left = window[0]; + const int top = window[1]; + const int right = window[2]; + const int bottom = window[3]; - unsigned width = header.window[2] - header.window[0] + 1; - unsigned height = header.window[3] - header.window[1] + 1; - unsigned bitcount = header.bpp * header.planes; - - if (bitcount == 24) { - dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, width, height, bitcount); + // check image size + if((left >= right) || (top >= bottom)) { + throw FI_MSG_ERROR_PARSING; } - // if the dib couldn't be allocated, throw an error + const unsigned width = right - left + 1; + const unsigned height = bottom - top + 1; + const unsigned bitcount = header.bpp * header.planes; + + // allocate a new DIB + switch(bitcount) { + case 1: + case 4: + case 8: + dib = FreeImage_AllocateHeader(header_only, width, height, bitcount); + break; + case 24: + dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + break; + default: + throw FI_MSG_ERROR_DIB_MEMORY; + break; + } + // if the dib couldn't be allocated, throw an error if (!dib) { throw FI_MSG_ERROR_DIB_MEMORY; } @@ -426,19 +446,23 @@ Load(FreeImageIO *io, fi_handle handle, if (palette_id == 0x0C) { BYTE *cmap = (BYTE*)malloc(768 * sizeof(BYTE)); - io->read_proc(cmap, 768, 1, handle); - pal = FreeImage_GetPalette(dib); - BYTE *pColormap = &cmap[0]; + if(cmap) { + io->read_proc(cmap, 768, 1, handle); - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = pColormap[0]; - pal[i].rgbGreen = pColormap[1]; - pal[i].rgbBlue = pColormap[2]; - pColormap += 3; + pal = FreeImage_GetPalette(dib); + BYTE *pColormap = &cmap[0]; + + for(int i = 0; i < 256; i++) { + pal[i].rgbRed = pColormap[0]; + pal[i].rgbGreen = pColormap[1]; + pal[i].rgbBlue = pColormap[2]; + pColormap += 3; + } + + free(cmap); } - free(cmap); } // wrong palette ID, perhaps a gray scale is needed ? @@ -466,9 +490,9 @@ Load(FreeImageIO *io, fi_handle handle, // calculate the line length for the PCX and the DIB // length of raster line in bytes - unsigned linelength = header.bytes_per_line * header.planes; + const unsigned linelength = header.bytes_per_line * header.planes; // length of DIB line (rounded to DWORD) in bytes - unsigned pitch = FreeImage_GetPitch(dib); + const unsigned pitch = FreeImage_GetPitch(dib); // run-length encoding ?