Skip to content

Commit a3ef34c

Browse files
committed
Fix cjpeg segfault when Windows BMP width/height<0
rdbmp.c used the ambiguous INT32 datatype, which is sometimes typedef'ed to long. Windows bitmap headers use 32-bit signed integers for the width and height, because height can sometimes be negative (this indicates a top-down bitmap.) If biWidth or biHeight was negative and INT32 was a 64-bit long, then biWidth and biHeight were read as a positive integer > INT32_MAX, which failed the test in line 385: if (biWidth <= 0 || biHeight <= 0) ERREXIT(cinfo, JERR_BMP_EMPTY); This commit refactors rdbmp.c so that it uses the datatypes specified by Microsoft for the Windows BMP header. This closes flutter#9 and also provides a better solution for mozilla/mozjpeg#153.
1 parent b1682fb commit a3ef34c

File tree

2 files changed

+39
-29
lines changed

2 files changed

+39
-29
lines changed

ChangeLog.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
1.4.2
2+
=====
3+
4+
[1] Fixed an issue whereby cjpeg would segfault if a Windows bitmap with a
5+
negative width or height was used as an input image (Windows bitmaps can have
6+
a negative height if they are stored in top-down order, but such files are
7+
rare and not supported by libjpeg-turbo.)
8+
9+
110
1.4.1
211
=====
312

rdbmp.c

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Modified 2009-2010 by Guido Vollbeding.
77
* libjpeg-turbo Modifications:
88
* Modified 2011 by Siarhei Siamashka.
9+
* Copyright (C) 2015, D. R. Commander.
910
* For conditions of distribution and use, see the accompanying README file.
1011
*
1112
* This file contains routines to read input images in Microsoft "BMP"
@@ -279,58 +280,58 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
279280
bmp_source_ptr source = (bmp_source_ptr) sinfo;
280281
U_CHAR bmpfileheader[14];
281282
U_CHAR bmpinfoheader[64];
282-
#define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \
283-
(((unsigned int) UCH(array[offset+1])) << 8))
284-
#define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \
285-
(((INT32) UCH(array[offset+1])) << 8) + \
286-
(((INT32) UCH(array[offset+2])) << 16) + \
287-
(((INT32) UCH(array[offset+3])) << 24))
288-
INT32 bfOffBits;
289-
INT32 headerSize;
290-
INT32 biWidth;
291-
INT32 biHeight;
292-
unsigned int biPlanes;
293-
INT32 biCompression;
294-
INT32 biXPelsPerMeter,biYPelsPerMeter;
295-
INT32 biClrUsed = 0;
283+
#define GET_2B(array,offset) ((unsigned short) UCH(array[offset]) + \
284+
(((unsigned short) UCH(array[offset+1])) << 8))
285+
#define GET_4B(array,offset) ((unsigned int) UCH(array[offset]) + \
286+
(((unsigned int) UCH(array[offset+1])) << 8) + \
287+
(((unsigned int) UCH(array[offset+2])) << 16) + \
288+
(((unsigned int) UCH(array[offset+3])) << 24))
289+
unsigned int bfOffBits;
290+
unsigned int headerSize;
291+
int biWidth;
292+
int biHeight;
293+
unsigned short biPlanes;
294+
unsigned int biCompression;
295+
int biXPelsPerMeter,biYPelsPerMeter;
296+
unsigned int biClrUsed = 0;
296297
int mapentrysize = 0; /* 0 indicates no colormap */
297-
INT32 bPad;
298+
int bPad;
298299
JDIMENSION row_width;
299300

300301
/* Read and verify the bitmap file header */
301302
if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
302303
ERREXIT(cinfo, JERR_INPUT_EOF);
303304
if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
304305
ERREXIT(cinfo, JERR_BMP_NOT);
305-
bfOffBits = (INT32) GET_4B(bmpfileheader,10);
306+
bfOffBits = GET_4B(bmpfileheader,10);
306307
/* We ignore the remaining fileheader fields */
307308

308309
/* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
309310
* or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which.
310311
*/
311312
if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
312313
ERREXIT(cinfo, JERR_INPUT_EOF);
313-
headerSize = (INT32) GET_4B(bmpinfoheader,0);
314+
headerSize = GET_4B(bmpinfoheader,0);
314315
if (headerSize < 12 || headerSize > 64)
315316
ERREXIT(cinfo, JERR_BMP_BADHEADER);
316317
if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4))
317318
ERREXIT(cinfo, JERR_INPUT_EOF);
318319

319-
switch ((int) headerSize) {
320+
switch (headerSize) {
320321
case 12:
321322
/* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
322-
biWidth = (INT32) GET_2B(bmpinfoheader,4);
323-
biHeight = (INT32) GET_2B(bmpinfoheader,6);
323+
biWidth = (int) GET_2B(bmpinfoheader,4);
324+
biHeight = (int) GET_2B(bmpinfoheader,6);
324325
biPlanes = GET_2B(bmpinfoheader,8);
325326
source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
326327

327328
switch (source->bits_per_pixel) {
328329
case 8: /* colormapped image */
329330
mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
330-
TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
331+
TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, biWidth, biHeight);
331332
break;
332333
case 24: /* RGB image */
333-
TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
334+
TRACEMS2(cinfo, 1, JTRC_BMP_OS2, biWidth, biHeight);
334335
break;
335336
default:
336337
ERREXIT(cinfo, JERR_BMP_BADDEPTH);
@@ -341,26 +342,26 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
341342
case 64:
342343
/* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
343344
/* or OS/2 2.x header, which has additional fields that we ignore */
344-
biWidth = GET_4B(bmpinfoheader,4);
345-
biHeight = GET_4B(bmpinfoheader,8);
345+
biWidth = (int) GET_4B(bmpinfoheader,4);
346+
biHeight = (int) GET_4B(bmpinfoheader,8);
346347
biPlanes = GET_2B(bmpinfoheader,12);
347348
source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
348349
biCompression = GET_4B(bmpinfoheader,16);
349-
biXPelsPerMeter = GET_4B(bmpinfoheader,24);
350-
biYPelsPerMeter = GET_4B(bmpinfoheader,28);
350+
biXPelsPerMeter = (int) GET_4B(bmpinfoheader,24);
351+
biYPelsPerMeter = (int) GET_4B(bmpinfoheader,28);
351352
biClrUsed = GET_4B(bmpinfoheader,32);
352353
/* biSizeImage, biClrImportant fields are ignored */
353354

354355
switch (source->bits_per_pixel) {
355356
case 8: /* colormapped image */
356357
mapentrysize = 4; /* Windows uses RGBQUAD colormap */
357-
TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
358+
TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, biWidth, biHeight);
358359
break;
359360
case 24: /* RGB image */
360-
TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
361+
TRACEMS2(cinfo, 1, JTRC_BMP, biWidth, biHeight);
361362
break;
362363
case 32: /* RGB image + Alpha channel */
363-
TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
364+
TRACEMS2(cinfo, 1, JTRC_BMP, biWidth, biHeight);
364365
break;
365366
default:
366367
ERREXIT(cinfo, JERR_BMP_BADDEPTH);

0 commit comments

Comments
 (0)