freeimage/CVE-2020-21427-1-r1832-improved-BMP-plugin-when-working-with-malicious-images.patch

446 lines
11 KiB
Diff
Raw Normal View History

Origin: upstream, r1832
Index: Source/FreeImage/PluginBMP.cpp
---
diff --git a/Source/FreeImage/PluginBMP.cpp b/Source/FreeImage/PluginBMP.cpp
--- a/Source/FreeImage/PluginBMP.cpp (revision 1831)
+++ b/Source/FreeImage/PluginBMP.cpp (revision 1832)
@@ -181,6 +181,7 @@
}
}
#endif
+
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
if (bit_count == 24 || bit_count == 32) {
for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
@@ -202,7 +203,7 @@
@param handle FreeImage IO handle
@param width Image width
@param height Image height
-@param dib Image to be loaded
+@param dib 4-bit image to be loaded
@return Returns TRUE if successful, returns FALSE otherwise
*/
static BOOL
@@ -217,7 +218,9 @@
height = abs(height);
pixels = (BYTE*)malloc(width * height * sizeof(BYTE));
- if(!pixels) throw(1);
+ if (!pixels) {
+ throw(1);
+ }
memset(pixels, 0, width * height * sizeof(BYTE));
BYTE *q = pixels;
@@ -237,7 +240,7 @@
throw(1);
}
for (int i = 0; i < status_byte; i++) {
- *q++=(BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
+ *q++ = (BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
}
bits += status_byte;
}
@@ -252,7 +255,7 @@
// End of line
bits = 0;
scanline++;
- q = pixels + scanline*width;
+ q = pixels + scanline * width;
}
break;
@@ -264,7 +267,6 @@
case RLE_DELTA:
{
// read the delta values
-
BYTE delta_x = 0;
BYTE delta_y = 0;
@@ -276,7 +278,6 @@
}
// apply them
-
bits += delta_x;
scanline += delta_y;
q = pixels + scanline*width+bits;
@@ -293,7 +294,7 @@
throw(1);
}
}
- *q++=(BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
+ *q++ = (BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
}
bits += status_byte;
// Read pad byte
@@ -334,7 +335,9 @@
return TRUE;
} catch(int) {
- if(pixels) free(pixels);
+ if (pixels) {
+ free(pixels);
+ }
return FALSE;
}
}
@@ -345,7 +348,7 @@
@param handle FreeImage IO handle
@param width Image width
@param height Image height
-@param dib Image to be loaded
+@param dib 8-bit image to be loaded
@return Returns TRUE if successful, returns FALSE otherwise
*/
static BOOL
@@ -354,103 +357,85 @@
BYTE second_byte = 0;
int scanline = 0;
int bits = 0;
+ int count = 0;
+ BYTE delta_x = 0;
+ BYTE delta_y = 0;
- for (;;) {
- if( io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ height = abs(height);
+
+ while(scanline < height) {
+
+ if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
return FALSE;
}
- switch (status_byte) {
- case RLE_COMMAND :
- if(io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
+ if (status_byte == RLE_COMMAND) {
+ if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
- switch (status_byte) {
- case RLE_ENDOFLINE :
- bits = 0;
- scanline++;
- break;
+ switch (status_byte) {
+ case RLE_ENDOFLINE:
+ bits = 0;
+ scanline++;
+ break;
- case RLE_ENDOFBITMAP :
- return TRUE;
+ case RLE_ENDOFBITMAP:
+ return TRUE;
- case RLE_DELTA :
- {
- // read the delta values
+ case RLE_DELTA:
+ // read the delta values
+ delta_x = 0;
+ delta_y = 0;
+ if (io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+ if (io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+ // apply them
+ bits += delta_x;
+ scanline += delta_y;
+ break;
- BYTE delta_x = 0;
- BYTE delta_y = 0;
-
- if(io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
- if(io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
-
- // apply them
-
- bits += delta_x;
- scanline += delta_y;
-
- break;
+ default:
+ // absolute mode
+ count = MIN((int)status_byte, width - bits);
+ if (count < 0) {
+ return FALSE;
}
-
- default :
- {
- if(scanline >= abs(height)) {
- return TRUE;
- }
-
- int count = MIN((int)status_byte, width - bits);
-
- BYTE *sline = FreeImage_GetScanLine(dib, scanline);
-
- if(io->read_proc((void *)(sline + bits), sizeof(BYTE) * count, 1, handle) != 1) {
+ BYTE *sline = FreeImage_GetScanLine(dib, scanline);
+ if (io->read_proc((void *)(sline + bits), sizeof(BYTE) * count, 1, handle) != 1) {
+ return FALSE;
+ }
+ // align run length to even number of bytes
+ if ((status_byte & 1) == 1) {
+ if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
return FALSE;
}
-
- // align run length to even number of bytes
-
- if ((status_byte & 1) == 1) {
- if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
- }
-
- bits += status_byte;
-
- break;
}
- }
+ bits += status_byte;
+ break;
- break;
-
- default :
- {
- if(scanline >= abs(height)) {
- return TRUE;
- }
-
- int count = MIN((int)status_byte, width - bits);
-
- BYTE *sline = FreeImage_GetScanLine(dib, scanline);
-
- if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
-
- for (int i = 0; i < count; i++) {
- *(sline + bits) = second_byte;
-
- bits++;
- }
-
- break;
+ } // switch (status_byte)
+ }
+ else {
+ count = MIN((int)status_byte, width - bits);
+ if (count < 0) {
+ return FALSE;
}
+ BYTE *sline = FreeImage_GetScanLine(dib, scanline);
+ if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+ for (int i = 0; i < count; i++) {
+ *(sline + bits) = second_byte;
+ bits++;
+ }
}
}
+
+ return FALSE;
}
// --------------------------------------------------------------------------
@@ -463,10 +448,12 @@
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
// load the info header
-
BITMAPINFOHEADER bih;
+ memset(&bih, 0, sizeof(BITMAPINFOHEADER));
+ if (io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1) {
+ throw FI_MSG_ERROR_INVALID_FORMAT;
+ }
- io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapInfoHeader(&bih);
#endif
@@ -544,7 +531,7 @@
break;
case BI_RLE4 :
- if( LoadPixelDataRLE4(io, handle, width, height, dib) ) {
+ if( (bit_count == 4) && LoadPixelDataRLE4(io, handle, width, height, dib) ) {
return dib;
} else {
throw "Error encountered while decoding RLE4 BMP data";
@@ -552,7 +539,7 @@
break;
case BI_RLE8 :
- if( LoadPixelDataRLE8(io, handle, width, height, dib) ) {
+ if( (bit_count == 8) && LoadPixelDataRLE8(io, handle, width, height, dib) ) {
return dib;
} else {
throw "Error encountered while decoding RLE8 BMP data";
@@ -602,7 +589,7 @@
return dib;
}
- break; // 16-bit
+ break; // 16-bit RGB
case 24 :
case 32 :
@@ -679,10 +666,12 @@
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
// load the info header
-
BITMAPINFOHEADER bih;
+ memset(&bih, 0, sizeof(BITMAPINFOHEADER));
+ if (io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1) {
+ throw FI_MSG_ERROR_INVALID_FORMAT;
+ }
- io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapInfoHeader(&bih);
#endif
@@ -767,17 +756,19 @@
return dib;
case BI_RLE4 :
- if( LoadPixelDataRLE4(io, handle, width, height, dib) ) {
+ if ((bit_count == 4) && LoadPixelDataRLE4(io, handle, width, height, dib)) {
return dib;
- } else {
+ }
+ else {
throw "Error encountered while decoding RLE4 BMP data";
}
break;
case BI_RLE8 :
- if( LoadPixelDataRLE8(io, handle, width, height, dib) ) {
+ if ((bit_count == 8) && LoadPixelDataRLE8(io, handle, width, height, dib)) {
return dib;
- } else {
+ }
+ else {
throw "Error encountered while decoding RLE8 BMP data";
}
break;
@@ -863,9 +854,9 @@
}
}
} catch(const char *message) {
- if(dib)
+ if (dib) {
FreeImage_Unload(dib);
-
+ }
FreeImage_OutputMessageProc(s_format_id, message);
}
@@ -881,9 +872,13 @@
try {
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
+ // load the info header
BITMAPINFOOS2_1X_HEADER bios2_1x;
+ memset(&bios2_1x, 0, sizeof(BITMAPINFOOS2_1X_HEADER));
+ if (io->read_proc(&bios2_1x, sizeof(BITMAPINFOOS2_1X_HEADER), 1, handle) != 1) {
+ throw FI_MSG_ERROR_INVALID_FORMAT;
+ }
- io->read_proc(&bios2_1x, sizeof(BITMAPINFOOS2_1X_HEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapOS21XHeader(&bios2_1x);
#endif
@@ -1005,9 +1000,9 @@
}
}
} catch(const char *message) {
- if(dib)
+ if (dib) {
FreeImage_Unload(dib);
-
+ }
FreeImage_OutputMessageProc(s_format_id, message);
}
@@ -1090,19 +1085,20 @@
BITMAPFILEHEADER bitmapfileheader;
DWORD type = 0;
- // we use this offset value to make seemingly absolute seeks relative in the file
-
+ // we use this offset value to make seemingly absolute seeks relative in the file
long offset_in_file = io->tell_proc(handle);
// read the fileheader
+ memset(&bitmapfileheader, 0, sizeof(BITMAPFILEHEADER));
+ if (io->read_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1) {
+ return NULL;
+ }
- io->read_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapFileHeader(&bitmapfileheader);
#endif
// check the signature
-
if((bitmapfileheader.bfType != 0x4D42) && (bitmapfileheader.bfType != 0x4142)) {
FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_MAGIC_NUMBER);
return NULL;
@@ -1109,9 +1105,9 @@
}
// read the first byte of the infoheader
-
io->read_proc(&type, sizeof(DWORD), 1, handle);
io->seek_proc(handle, 0 - (long)sizeof(DWORD), SEEK_CUR);
+
#ifdef FREEIMAGE_BIGENDIAN
SwapLong(&type);
#endif
@@ -1138,7 +1134,7 @@
break;
}
- FreeImage_OutputMessageProc(s_format_id, "unknown bmp subtype with id %d", type);
+ FreeImage_OutputMessageProc(s_format_id, "Unknown bmp subtype with id %d", type);
}
return NULL;
@@ -1418,6 +1414,7 @@
}
free(buffer);
+
#ifdef FREEIMAGE_BIGENDIAN
} else if (dst_bpp == 16) {
int padding = dst_pitch - dst_width * sizeof(WORD);
@@ -1439,6 +1436,7 @@
}
}
#endif
+
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
} else if (dst_bpp == 24) {
int padding = dst_pitch - dst_width * sizeof(FILE_BGR);