CVE-2019-15139: Out-of-bounds Read (CWE-125)
value: The XWD image (X Window System window dumping file) parsing component in ImageMagick 7.0.8-41 Q16 allows attackers to cause a denial-of-service (application crash resulting from an out-of-bounds Read) in ReadXWDImage in coders/xwd.c by crafting a corrupted XWD image file, a different vulnerability than CVE-2019-11472.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 6.5
Published: 2019-08-18T19:15Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: coders/xwd.c
Commit date: 2019-04-20 09:40:12 -0400
Commit message: https://github.com/ImageMagick/ImageMagick/issues/1553

Diff: diff --git a/coders/xwd.c b/coders/xwd.c
index 236fbdb5ab57..0074811a060d 100644
--- a/coders/xwd.c
+++ b/coders/xwd.c
@@ -236,10 +236,12 @@ static Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception)
   */
   if (header.file_version != XWD_FILE_VERSION)
     ThrowReaderException(CorruptImageError,"FileFormatVersionMismatch");
   if (header.header_size < sz_XWDheader)
     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+  if ((MagickSizeType) header.xoffset >= GetBlobSize(image))
+    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   switch (header.visual_class)
   {
     case StaticGray:
     case GrayScale:
     {
@@ -249,11 +251,11 @@ static Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception)
     }
     case StaticColor:
     case PseudoColor:
     {
       if ((header.bits_per_pixel < 1) || (header.bits_per_pixel > 15) ||
-          (header.ncolors == 0))
+          (header.colormap_entries == 0))
         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
       break;
     }
     case TrueColor:
     case DirectColor:
@@ -316,12 +318,10 @@ static Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception)
     case MSBFirst:
       break;
     default:
       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   }
-  if (header.ncolors > 65535)
-    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   if (((header.bitmap_pad % 8) != 0) || (header.bitmap_pad > 32))
     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   length=(size_t) (header.header_size-sz_XWDheader);
   comment=(char *) AcquireQuantumMemory(length+1,sizeof(*comment));
   if (comment == (char *) NULL)
@@ -385,12 +385,14 @@ static Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception)
   if (header.ncolors != 0)
     {
       XWDColor
         color;
 
-      colors=(XColor *) AcquireQuantumMemory((size_t) header.ncolors,
-        sizeof(*colors));
+      length=(size_t) header.ncolors;
+      if (length > ((~0UL)/sizeof(*colors)))
+        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      colors=(XColor *) AcquireQuantumMemory(length,sizeof(*colors));
       if (colors == (XColor *) NULL)
         {
           ximage=(XImage *) RelinquishMagickMemory(ximage);
           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
@@ -687,10 +689,11 @@ ModuleExport size_t RegisterXWDImage(void)
 #if defined(MAGICKCORE_X11_DELEGATE)
   entry->decoder=(DecodeImageHandler *) ReadXWDImage;
   entry->encoder=(EncodeImageHandler *) WriteXWDImage;
 #endif
   entry->magick=(IsImageFormatHandler *) IsXWD;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   entry->flags^=CoderAdjoinFlag;
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);
 }
 

Vulnerable code:           (header.ncolors == 0))
  if (header.ncolors > 65535)
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
      colors=(XColor *) AcquireQuantumMemory((size_t) header.ncolors,
        sizeof(*colors));
Fixed code:   if ((MagickSizeType) header.xoffset >= GetBlobSize(image))
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
          (header.colormap_entries == 0))
      length=(size_t) header.ncolors;
      if (length > ((~0UL)/sizeof(*colors)))
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
      colors=(XColor *) AcquireQuantumMemory(length,sizeof(*colors));
  entry->flags|=CoderDecoderSeekableStreamFlag;