Vulnerability: The function InsertRow in coders/cut.c in ImageMagick 7.0.7-37 allows remote attackers to cause a denial of service via a crafted image file due to an out-of-bounds write.
Vulnerability ID: CVE-2018-16642
CWE: CWE-787
Severity score: 2.9
Project: https://github.com/ImageMagick/ImageMagick
Published: 2018-09-06
File: coders/cut.c
Commit message: https://github.com/ImageMagick/ImageMagick/issues/1162
Commit author: Cristy

Vulnerable version (before fix):
 typedef struct } CUTPalHeader;   static void InsertRow(Image *image,ssize_t depth,unsigned char *p,ssize_t y,   ExceptionInfo *exception) {   size_t bit; ssize_t x;   register Quantum *q;   Quantum index;    index=0;   switch (depth)   {     case 1:  /* Convert bitmap scanline. */       {         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);         if (q == (Quantum *) NULL)           break;         for (x=0; x < ((ssize_t) image->columns-7); x+=8)         {           for (bit=0; bit < 8; bit++)           {             index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);             SetPixelIndex(image,index,q);             q+=GetPixelChannels(image);           }           p++;         }         if ((image->columns % 8) != 0)           {             for (bit=0; bit < (image->columns % 8); bit++)               {                 index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);                 SetPixelIndex(image,index,q);                 q+=GetPixelChannels(image);               }             p++;           }         (void) SyncAuthenticPixels(image,exception);         break;       }     case 2:  /* Convert PseudoColor scanline. */       {         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);         if (q == (Quantum *) NULL)           break;         for (x=0; x < ((ssize_t) image->columns-1); x+=2)         {           index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);           SetPixelIndex(image,index,q);           q+=GetPixelChannels(image);           index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);           SetPixelIndex(image,index,q);           q+=GetPixelChannels(image);           index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);           SetPixelIndex(image,index,q);           q+=GetPixelChannels(image);           index=ConstrainColormapIndex(image,(*p) & 0x3,exception);           SetPixelIndex(image,index,q);           q+=GetPixelChannels(image);           p++;         }         if ((image->columns % 4) != 0)           {             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);             SetPixelIndex(image,index,q);             q+=GetPixelChannels(image);             if ((image->columns % 4) >= 1)                {                 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);                 SetPixelIndex(image,index,q);                 q+=GetPixelChannels(image);                 if ((image->columns % 4) >= 2)                    {                     index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,                       exception);                     SetPixelIndex(image,index,q);                     q+=GetPixelChannels(image);                   }               }             p++;           }         (void) SyncAuthenticPixels(image,exception);         break;       }      case 4:  /* Convert PseudoColor scanline. */       {         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);         if (q == (Quantum *) NULL)           break;         for (x=0; x < ((ssize_t) image->columns-1); x+=2)         {             index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);             SetPixelIndex(image,index,q);             q+=GetPixelChannels(image);             index=ConstrainColormapIndex(image,(*p) & 0xf,exception);             SetPixelIndex(image,index,q);             q+=GetPixelChannels(image);             p++;           }         if ((image->columns % 2) != 0)           {             index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);             SetPixelIndex(image,index,q);             q+=GetPixelChannels(image);             p++;           }         (void) SyncAuthenticPixels(image,exception);         break;       }     case 8: /* Convert PseudoColor scanline. */       {         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);         if (q == (Quantum *) NULL)           break;         for (x=0; x < (ssize_t) image->columns; x++)         {           index=ConstrainColormapIndex(image,*p,exception);           SetPixelIndex(image,index,q);           p++;           q+=GetPixelChannels(image);         }         (void) SyncAuthenticPixels(image,exception);         break;       }     } }  /*

Fixed version (after fix):
 typedef struct } CUTPalHeader;   static MagickBooleanType InsertRow(Image *image,ssize_t bpp,unsigned char *p,   ssize_t y,ExceptionInfo *exception) {   int     bit;    Quantum     index;    register Quantum     *q;    ssize_t     x;    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);   if (q == (Quantum *) NULL)     return(MagickFalse);   switch (bpp)     {     case 1:  /* Convert bitmap scanline. */       {         for (x=0; x < ((ssize_t) image->columns-7); x+=8)         {           for (bit=0; bit < 8; bit++)           {             index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             q+=GetPixelChannels(image);           }           p++;         }         if ((image->columns % 8) != 0)           {             for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)             {               index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);               SetPixelIndex(image,index,q);               if (index < image->colors)                 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);               q+=GetPixelChannels(image);             }             p++;           }         break;       }     case 2:  /* Convert PseudoColor scanline. */       {         for (x=0; x < ((ssize_t) image->columns-3); x+=4)         {             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             q+=GetPixelChannels(image);             index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             q+=GetPixelChannels(image);             index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             q+=GetPixelChannels(image);             index=ConstrainColormapIndex(image,(*p) & 0x3,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             q+=GetPixelChannels(image);             p++;         }        if ((image->columns % 4) != 0)           {             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             q+=GetPixelChannels(image);             if ((image->columns % 4) > 1)               {                 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);                 SetPixelIndex(image,index,q);                 if (index < image->colors)                   SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);                 q+=GetPixelChannels(image);                 if ((image->columns % 4) > 2)                   {                     index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,                       exception);                     SetPixelIndex(image,index,q);                     if (index < image->colors)                       SetPixelViaPixelInfo(image,image->colormap+(ssize_t)                         index,q);                     q+=GetPixelChannels(image);                   }               }             p++;           }         break;       }      case 4:  /* Convert PseudoColor scanline. */       {         for (x=0; x < ((ssize_t) image->columns-1); x+=2)           {             index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             q+=GetPixelChannels(image);             index=ConstrainColormapIndex(image,(*p) & 0x0f,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             p++;             q+=GetPixelChannels(image);           }         if ((image->columns % 2) != 0)           {             index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             p++;             q+=GetPixelChannels(image);           }         break;       }     case 8: /* Convert PseudoColor scanline. */       {         for (x=0; x < (ssize_t) image->columns; x++)           {             index=ConstrainColormapIndex(image,*p,exception);             SetPixelIndex(image,index,q);             if (index < image->colors)               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);             p++;             q+=GetPixelChannels(image);           }       }       break;      case 24:     /*  Convert DirectColor scanline.  */       for (x=0; x < (ssize_t) image->columns; x++)         {           SetPixelRed(image,ScaleCharToQuantum(*p++),q);           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);           q+=GetPixelChannels(image);         }       break;     }   if (!SyncAuthenticPixels(image,exception))     return(MagickFalse);   return(MagickTrue); }  /*

Patch:
patch: @@ -95,132 +95,165 @@ typedef struct
 } CUTPalHeader;
 
 
-static void InsertRow(Image *image,ssize_t depth,unsigned char *p,ssize_t y,
-  ExceptionInfo *exception)
+static MagickBooleanType InsertRow(Image *image,ssize_t bpp,unsigned char *p,
+  ssize_t y,ExceptionInfo *exception)
 {
-  size_t bit; ssize_t x;
-  register Quantum *q;
-  Quantum index;
+  int
+    bit;
 
-  index=0;
-  switch (depth)
-  {
+  Quantum
+    index;
+
+  register Quantum
+    *q;
+
+  ssize_t
+    x;
+
+  q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
+  if (q == (Quantum *) NULL)
+    return(MagickFalse);
+  switch (bpp)
+    {
     case 1:  /* Convert bitmap scanline. */
       {
-        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (Quantum *) NULL)
-          break;
         for (x=0; x < ((ssize_t) image->columns-7); x+=8)
         {
           for (bit=0; bit < 8; bit++)
           {
-            index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
+            index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
             SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             q+=GetPixelChannels(image);
           }
           p++;
         }
         if ((image->columns % 8) != 0)
           {
-            for (bit=0; bit < (image->columns % 8); bit++)
-              {
-                index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
-                SetPixelIndex(image,index,q);
-                q+=GetPixelChannels(image);
-              }
+            for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
+            {
+              index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
+              SetPixelIndex(image,index,q);
+              if (index < image->colors)
+                SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
+              q+=GetPixelChannels(image);
+            }
             p++;
           }
-        (void) SyncAuthenticPixels(image,exception);
         break;
       }
     case 2:  /* Convert PseudoColor scanline. */
       {
-        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (Quantum *) NULL)
-          break;
-        for (x=0; x < ((ssize_t) image->columns-1); x+=2)
+        for (x=0; x < ((ssize_t) image->columns-3); x+=4)
         {
-          index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
-          SetPixelIndex(image,index,q);
-          q+=GetPixelChannels(image);
-          index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
-          SetPixelIndex(image,index,q);
-          q+=GetPixelChannels(image);
-          index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);
-          SetPixelIndex(image,index,q);
-          q+=GetPixelChannels(image);
-          index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
-          SetPixelIndex(image,index,q);
-          q+=GetPixelChannels(image);
-          p++;
+            index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            p++;
         }
-        if ((image->columns % 4) != 0)
+       if ((image->columns % 4) != 0)
           {
             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
             SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             q+=GetPixelChannels(image);
-            if ((image->columns % 4) >= 1)
-
+            if ((image->columns % 4) > 1)
               {
                 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
                 SetPixelIndex(image,index,q);
+                if (index < image->colors)
+                  SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
                 q+=GetPixelChannels(image);
-                if ((image->columns % 4) >= 2)
-
+                if ((image->columns % 4) > 2)
                   {
                     index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,
                       exception);
                     SetPixelIndex(image,index,q);
+                    if (index < image->colors)
+                      SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
+                        index,q);
                     q+=GetPixelChannels(image);
                   }
               }
             p++;
           }
-        (void) SyncAuthenticPixels(image,exception);
         break;
       }
 
     case 4:  /* Convert PseudoColor scanline. */
       {
-        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (Quantum *) NULL)
-          break;
         for (x=0; x < ((ssize_t) image->columns-1); x+=2)
-        {
-            index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
+          {
+            index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
             SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             q+=GetPixelChannels(image);
-            index=ConstrainColormapIndex(image,(*p) & 0xf,exception);
+            index=ConstrainColormapIndex(image,(*p) & 0x0f,exception);
             SetPixelIndex(image,index,q);
-            q+=GetPixelChannels(image);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             p++;
+            q+=GetPixelChannels(image);
           }
         if ((image->columns % 2) != 0)
           {
-            index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
+            index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
             SetPixelIndex(image,index,q);
-            q+=GetPixelChannels(image);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             p++;
+            q+=GetPixelChannels(image);
           }
-        (void) SyncAuthenticPixels(image,exception);
         break;
       }
     case 8: /* Convert PseudoColor scanline. */
       {
-        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (Quantum *) NULL)
-          break;
         for (x=0; x < (ssize_t) image->columns; x++)
+          {
+            index=ConstrainColormapIndex(image,*p,exception);
+            SetPixelIndex(image,index,q);
+            if (index < image->colors)
+              SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
+            p++;
+            q+=GetPixelChannels(image);
+          }
+      }
+      break;
+
+    case 24:     /*  Convert DirectColor scanline.  */
+      for (x=0; x < (ssize_t) image->columns; x++)
         {
-          index=ConstrainColormapIndex(image,*p,exception);
-          SetPixelIndex(image,index,q);
-          p++;
+          SetPixelRed(image,ScaleCharToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
           q+=GetPixelChannels(image);
         }
-        (void) SyncAuthenticPixels(image,exception);
-        break;
-      }
+      break;
     }
+  if (!SyncAuthenticPixels(image,exception))
+    return(MagickFalse);
+  return(MagickTrue);
 }
 
 /*
path: coders/cut.c