From 33375f93a866830bbaf72f86314fbc3014b9e4c4 Mon Sep 17 00:00:00 2001
From: Jake Lodwick <jakelodwick@users.noreply.github.com>
Date: Sat, 28 Feb 2026 08:39:45 -0700
Subject: [PATCH] Add overflow checks to BMP/DIB write paths and DIB read path
 (#8573)

---
 coders/bmp.c |  3 +++
 coders/dib.c | 28 +++++++++++++++++++++-------
 2 files changed, 24 insertions(+), 7 deletions(-)

Index: ImageMagick-7.1.1-21/coders/bmp.c
===================================================================
--- ImageMagick-7.1.1-21.orig/coders/bmp.c
+++ ImageMagick-7.1.1-21/coders/bmp.c
@@ -1107,6 +1107,9 @@ static Image *ReadBMPImage(const ImageIn
     offset=SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET);
     if (offset < 0)
       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+    if (BMPOverflowCheck(image->columns,(size_t) bmp_info.bits_per_pixel) !=
+        MagickFalse)
+      ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
     if (bmp_info.compression == BI_RLE4)
       bmp_info.bits_per_pixel<<=1;
     if (BMPOverflowCheck(image->columns,bmp_info.bits_per_pixel) != MagickFalse)
Index: ImageMagick-7.1.1-21/coders/dib.c
===================================================================
--- ImageMagick-7.1.1-21.orig/coders/dib.c
+++ ImageMagick-7.1.1-21/coders/dib.c
@@ -490,6 +490,7 @@ static Image *ReadDIBImage(const ImageIn
 
   size_t
     bytes_per_line,
+    extent,
     length;
 
   ssize_t
@@ -668,9 +669,15 @@ static Image *ReadDIBImage(const ImageIn
   */
   if (dib_info.compression == DibRle4Compression)
     dib_info.bits_per_pixel<<=1;
-  bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
-  length=bytes_per_line*image->rows;
-  if ((MagickSizeType) length > (256*GetBlobSize(image)))
+  if (HeapOverflowSanityCheckGetSize(image->columns,
+      (size_t) dib_info.bits_per_pixel,&extent) != MagickFalse)
+    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+  if (HeapOverflowSanityCheckGetSize(4,((extent+31)/32),&bytes_per_line) != MagickFalse)
+    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+  if (HeapOverflowSanityCheckGetSize(bytes_per_line,image->rows,
+      &length) != MagickFalse)
+    ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
+  if ((MagickSizeType) (length/256) > GetBlobSize(image))
     ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
   pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line,
     image->columns+256UL)*sizeof(*pixels));
@@ -1111,7 +1118,9 @@ static MagickBooleanType WriteDIBImage(c
     *q;
 
   size_t
-    bytes_per_line;
+    bytes_per_line,
+    extent,
+    length;
 
   ssize_t
     y;
@@ -1163,14 +1172,20 @@ static MagickBooleanType WriteDIBImage(c
       dib_info.number_colors=(unsigned int) (dib_info.bits_per_pixel == 16 ? 0 :
         (1UL << dib_info.bits_per_pixel));
     }
-  bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
+  if (HeapOverflowSanityCheckGetSize(image->columns,
+      (size_t) dib_info.bits_per_pixel,&extent) != MagickFalse)
+    ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
+  bytes_per_line=4*((extent+31)/32);
+  if (HeapOverflowSanityCheckGetSize(bytes_per_line,image->rows,
+      &length) != MagickFalse)
+    ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
   dib_info.size=40;
   dib_info.width=(int) image->columns;
   dib_info.height=(int) image->rows;
   dib_info.planes=1;
   dib_info.compression=(unsigned int) (dib_info.bits_per_pixel == 16 ?
     DibBitfieldsCompression : DibRgbCompression);
-  dib_info.image_size=(unsigned int) (bytes_per_line*image->rows);
+  dib_info.image_size=(unsigned int) length;
   dib_info.x_pixels=75*39;
   dib_info.y_pixels=75*39;
   switch (image->units)
@@ -1197,7 +1212,7 @@ static MagickBooleanType WriteDIBImage(c
     bytes_per_line,image->columns+256UL)*sizeof(*pixels));
   if (pixels == (unsigned char *) NULL)
     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
-  (void) memset(pixels,0,dib_info.image_size);
+  (void) memset(pixels,0,length);
   switch (dib_info.bits_per_pixel)
   {
     case 1:
