Add sanity check in BMP reader module to avoid cjpeg crash for empty input

image; Support 32-bit BMPs
This commit is contained in:
DRC
2010-10-10 07:25:16 +00:00
parent 153f54b94f
commit a119e8f8d0

57
rdbmp.c
View File

@@ -2,6 +2,7 @@
* rdbmp.c * rdbmp.c
* *
* Copyright (C) 1994-1996, Thomas G. Lane. * Copyright (C) 1994-1996, Thomas G. Lane.
* Modified 2009-2010 by Guido Vollbeding.
* This file is part of the Independent JPEG Group's software. * This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file. * For conditions of distribution and use, see the accompanying README file.
* *
@@ -177,10 +178,41 @@ get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
} }
METHODDEF(JDIMENSION)
get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 32-bit pixels */
{
bmp_source_ptr source = (bmp_source_ptr) sinfo;
JSAMPARRAY image_ptr;
register JSAMPROW inptr, outptr;
register JDIMENSION col;
/* Fetch next row from virtual array */
source->source_row--;
image_ptr = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, source->whole_image,
source->source_row, (JDIMENSION) 1, FALSE);
/* Transfer data. Note source values are in BGR order
* (even though Microsoft's own documents say the opposite).
*/
inptr = image_ptr[0];
outptr = source->pub.buffer[0];
for (col = cinfo->image_width; col > 0; col--) {
outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
outptr[1] = *inptr++;
outptr[0] = *inptr++;
inptr++; /* skip the 4th byte (Alpha channel) */
outptr += 3;
}
return 1;
}
/* /*
* This method loads the image into whole_image during the first call on * This method loads the image into whole_image during the first call on
* get_pixel_rows. The get_pixel_rows pointer is then adjusted to call * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
* get_8bit_row or get_24bit_row on subsequent calls. * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls.
*/ */
METHODDEF(JDIMENSION) METHODDEF(JDIMENSION)
@@ -223,6 +255,9 @@ preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
case 24: case 24:
source->pub.get_pixel_rows = get_24bit_row; source->pub.get_pixel_rows = get_24bit_row;
break; break;
case 32:
source->pub.get_pixel_rows = get_32bit_row;
break;
default: default:
ERREXIT(cinfo, JERR_BMP_BADDEPTH); ERREXIT(cinfo, JERR_BMP_BADDEPTH);
} }
@@ -251,8 +286,8 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
(((INT32) UCH(array[offset+3])) << 24)) (((INT32) UCH(array[offset+3])) << 24))
INT32 bfOffBits; INT32 bfOffBits;
INT32 headerSize; INT32 headerSize;
INT32 biWidth = 0; /* initialize to avoid compiler warning */ INT32 biWidth;
INT32 biHeight = 0; INT32 biHeight;
unsigned int biPlanes; unsigned int biPlanes;
INT32 biCompression; INT32 biCompression;
INT32 biXPelsPerMeter,biYPelsPerMeter; INT32 biXPelsPerMeter,biYPelsPerMeter;
@@ -300,8 +335,6 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
ERREXIT(cinfo, JERR_BMP_BADDEPTH); ERREXIT(cinfo, JERR_BMP_BADDEPTH);
break; break;
} }
if (biPlanes != 1)
ERREXIT(cinfo, JERR_BMP_BADPLANES);
break; break;
case 40: case 40:
case 64: case 64:
@@ -325,12 +358,13 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
case 24: /* RGB image */ case 24: /* RGB image */
TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
break; break;
case 32: /* RGB image + Alpha channel */
TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
break;
default: default:
ERREXIT(cinfo, JERR_BMP_BADDEPTH); ERREXIT(cinfo, JERR_BMP_BADDEPTH);
break; break;
} }
if (biPlanes != 1)
ERREXIT(cinfo, JERR_BMP_BADPLANES);
if (biCompression != 0) if (biCompression != 0)
ERREXIT(cinfo, JERR_BMP_COMPRESSED); ERREXIT(cinfo, JERR_BMP_COMPRESSED);
@@ -343,9 +377,14 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
break; break;
default: default:
ERREXIT(cinfo, JERR_BMP_BADHEADER); ERREXIT(cinfo, JERR_BMP_BADHEADER);
break; return;
} }
if (biWidth <= 0 || biHeight <= 0)
ERREXIT(cinfo, JERR_BMP_EMPTY);
if (biPlanes != 1)
ERREXIT(cinfo, JERR_BMP_BADPLANES);
/* Compute distance to bitmap data --- will adjust for colormap below */ /* Compute distance to bitmap data --- will adjust for colormap below */
bPad = bfOffBits - (headerSize + 14); bPad = bfOffBits - (headerSize + 14);
@@ -375,6 +414,8 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* Compute row width in file, including padding to 4-byte boundary */ /* Compute row width in file, including padding to 4-byte boundary */
if (source->bits_per_pixel == 24) if (source->bits_per_pixel == 24)
row_width = (JDIMENSION) (biWidth * 3); row_width = (JDIMENSION) (biWidth * 3);
else if (source->bits_per_pixel == 32)
row_width = (JDIMENSION) (biWidth * 4);
else else
row_width = (JDIMENSION) biWidth; row_width = (JDIMENSION) biWidth;
while ((row_width & 3) != 0) row_width++; while ((row_width & 3) != 0) row_width++;