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

160 lines
4.4 KiB
Diff

Origin: upstream, r1836
Index: Source/FreeImage/PluginBMP.cpp
---
diff --git a/Source/FreeImage/PluginBMP.cpp b/Source/FreeImage/PluginBMP.cpp
--- a/Source/FreeImage/PluginBMP.cpp (revision 1835)
+++ b/Source/FreeImage/PluginBMP.cpp (revision 1836)
@@ -139,6 +139,75 @@
// --------------------------------------------------------------------------
/**
+Check if a BITMAPINFOHEADER is valid
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL
+CheckBitmapInfoHeader(BITMAPINFOHEADER *bih) {
+ if (bih->biSize != sizeof(BITMAPINFOHEADER)) {
+ // The size, in bytes, of the image.This may be set to zero for BI_RGB bitmaps.
+ // If biCompression is BI_JPEG or BI_PNG, biSizeImage indicates the size of the JPEG or PNG image buffer, respectively.
+ if ((bih->biSize == 0) && (bih->biCompression != BI_RGB)) {
+ return FALSE;
+ }
+ else if ((bih->biCompression == BI_JPEG) || (bih->biCompression == BI_PNG)) {
+ // JPEG or PNG is not yet supported
+ return FALSE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+ if (bih->biWidth < 0) {
+ return FALSE;
+ }
+ if (bih->biHeight < 0) {
+ // If biHeight is negative, indicating a top-down DIB, biCompression must be either BI_RGB or BI_BITFIELDS.
+ // Top-down DIBs cannot be compressed.
+ // If biCompression is BI_JPEG or BI_PNG, the biHeight member specifies the height of the decompressed JPEG or PNG image file, respectively.
+ if ((bih->biCompression != BI_RGB) && (bih->biCompression != BI_BITFIELDS)) {
+ return FALSE;
+ }
+ }
+ if (bih->biPlanes != 1) {
+ // The number of planes for the target device. This value must be set to 1.
+ return FALSE;
+ }
+ switch (bih->biBitCount) {
+ case 0:
+ // The number of bits-per-pixel is specified or is implied by the JPEG or PNG format.
+ // JPEG or PNG is not yet supported
+ return FALSE;
+ break;
+ case 1:
+ case 4:
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ // Unsupported bitdepth
+ return FALSE;
+ }
+ switch (bih->biCompression) {
+ case BI_RGB:
+ case BI_RLE8:
+ case BI_RLE4:
+ case BI_BITFIELDS:
+ break;
+ case BI_JPEG:
+ case BI_PNG:
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// --------------------------------------------------------------------------
+
+/**
Load uncompressed image pixels for 1-, 4-, 8-, 16-, 24- and 32-bit dib
@param io FreeImage IO
@param handle FreeImage IO handle
@@ -458,6 +527,10 @@
SwapInfoHeader(&bih);
#endif
+ if (CheckBitmapInfoHeader(&bih) == FALSE) {
+ throw FI_MSG_ERROR_INVALID_FORMAT;
+ }
+
// keep some general information about the bitmap
unsigned used_colors = bih.biClrUsed;
@@ -555,10 +628,18 @@
case 16 :
{
int use_bitfields = 0;
- if (bih.biCompression == BI_BITFIELDS) use_bitfields = 3;
- else if (bih.biCompression == BI_ALPHABITFIELDS) use_bitfields = 4;
- else if (type == 52) use_bitfields = 3;
- else if (type >= 56) use_bitfields = 4;
+ if (bih.biCompression == BI_BITFIELDS) {
+ use_bitfields = 3;
+ }
+ else if (bih.biCompression == BI_ALPHABITFIELDS) {
+ use_bitfields = 4;
+ }
+ else if (type == 52) {
+ use_bitfields = 3;
+ }
+ else if (type >= 56) {
+ use_bitfields = 4;
+ }
if (use_bitfields > 0) {
DWORD bitfields[4];
@@ -595,10 +676,18 @@
case 32 :
{
int use_bitfields = 0;
- if (bih.biCompression == BI_BITFIELDS) use_bitfields = 3;
- else if (bih.biCompression == BI_ALPHABITFIELDS) use_bitfields = 4;
- else if (type == 52) use_bitfields = 3;
- else if (type >= 56) use_bitfields = 4;
+ if (bih.biCompression == BI_BITFIELDS) {
+ use_bitfields = 3;
+ }
+ else if (bih.biCompression == BI_ALPHABITFIELDS) {
+ use_bitfields = 4;
+ }
+ else if (type == 52) {
+ use_bitfields = 3;
+ }
+ else if (type >= 56) {
+ use_bitfields = 4;
+ }
if (use_bitfields > 0) {
DWORD bitfields[4];
@@ -676,6 +765,10 @@
SwapInfoHeader(&bih);
#endif
+ if (CheckBitmapInfoHeader(&bih) == FALSE) {
+ throw FI_MSG_ERROR_INVALID_FORMAT;
+ }
+
// keep some general information about the bitmap
unsigned used_colors = bih.biClrUsed;
@@ -780,7 +873,7 @@
case 16 :
{
- if (bih.biCompression == 3) {
+ if (bih.biCompression == BI_BITFIELDS) {
DWORD bitfields[3];
io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);