CVE-2016-7526: Out-of-bounds Write (CWE-787)
value: coders/wpg.c in ImageMagick allows remote attackers to cause a denial of service (out-of-bounds write) via a crafted file.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 6.5
Published: 2017-04-20T18:59Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: coders/wpg.c
Commit date: 2016-02-06 12:08:45 +0100
Commit message: Fixed out-of-bounds write reported in: https://github.com/ImageMagick/ImageMagick/issues/102

Diff: diff --git a/coders/wpg.c b/coders/wpg.c
index b01dcf9cc6..68d68c43af 100644
--- a/coders/wpg.c
+++ b/coders/wpg.c
@@ -315,11 +315,11 @@ static void InsertRow(Image *image,unsigned char *p,ssize_t y,int bpp,
     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+=4)
+        for (x=0; x < ((ssize_t) image->columns-3); x+=4)
         {
             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
             SetPixelIndex(image,index,q);
             SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             q+=GetPixelChannels(image);
@@ -332,28 +332,26 @@ static void InsertRow(Image *image,unsigned char *p,ssize_t y,int bpp,
             SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             q+=GetPixelChannels(image);
             index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
             SetPixelIndex(image,index,q);
             SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
-            p++;
             q+=GetPixelChannels(image);
+            p++;
         }
        if ((image->columns % 4) != 0)
           {
             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
             SetPixelIndex(image,index,q);
             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);
                 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);
                     SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
@@ -425,11 +423,11 @@ static void InsertRow(Image *image,unsigned char *p,ssize_t y,int bpp,
           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
           q+=GetPixelChannels(image);
         }
       if (!SyncAuthenticPixels(image,exception))
         break;
-      break;     
+      break;
     }
 }
 
 
 /* Helper for WPG1 raster reader. */
@@ -1181,37 +1179,36 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
 
                       flip_image = FlipImage(image, exception);
                       if (flip_image != (Image *) NULL) {
                         DuplicateBlob(flip_image,image);
                         (void) RemoveLastImageFromList(&image);
-                        AppendImageToList(&image,flip_image);    
+                        AppendImageToList(&image,flip_image);
                       }
                     }
-    
-      /* rotate command */
+                  /* rotate command */
                   if(BitmapHeader2.RotAngle & 0x0FFF)
                     {
                       Image
                         *rotate_image;
 
                       rotate_image=RotateImage(image,(BitmapHeader2.RotAngle &
                         0x0FFF), exception);
                       if (rotate_image != (Image *) NULL) {
                         DuplicateBlob(rotate_image,image);
                         (void) RemoveLastImageFromList(&image);
-                        AppendImageToList(&image,rotate_image);    
+                        AppendImageToList(&image,rotate_image);
                       }
-                    }                
+                    }
                 }
 
               /* Allocate next image structure. */
               AcquireNextImage(image_info,image,exception);
               image->depth=8;
               if (image->next == (Image *) NULL)
                 goto Finish;
               image=SyncNextImageInList(image);
-              image->columns=image->rows=0;
+              image->columns=image->rows=1;
               image->colors=0;
               break;
 
             case 0x1B:  /* Postscript l2 */
               if(Rec.RecordLength>0x3C)
@@ -1301,11 +1298,11 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                   break;
                 default:
                   continue;  /*Ignore raster with unknown depth*/
                 }
               image->columns=Bitmap2Header1.Width;
-              image->rows=Bitmap2Header1.Height;  
+              image->rows=Bitmap2Header1.Height;
 
               if ((image->colors == 0) && (bpp != 24))
                 {
                   size_t
                     one;
@@ -1340,11 +1337,11 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                         (void) ReadBlob(image,ldblk,BImgBuff);
                         InsertRow(image,BImgBuff,i,bpp,exception);
                       }
 
                     if(BImgBuff)
-                      BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);;
+                      BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
                     break;
                   }
                 case 1:    /*RLE for WPG2 */
                   {
                     if( UnpackWPG2Raster(image,bpp,exception) < 0)
@@ -1362,15 +1359,15 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                   if (flop_image != (Image *) NULL) {
                     DuplicateBlob(flop_image,image);
                     (void) RemoveLastImageFromList(&image);
                     AppendImageToList(&image,flop_image);
                   }
-                  /* Try to change CTM according to Flip - I am not sure, must be checked.      
+                  /* Try to change CTM according to Flip - I am not sure, must be checked.
                      Tx(0,0)=-1;      Tx(1,0)=0;   Tx(2,0)=0;
                      Tx(0,1)= 0;      Tx(1,1)=1;   Tx(2,1)=0;
                      Tx(0,2)=(WPG._2Rect.X_ur+WPG._2Rect.X_ll);
-                     Tx(1,2)=0;   Tx(2,2)=1; */                  
+                     Tx(1,2)=0;   Tx(2,2)=1; */
                 }
               if(CTM[1][1]<0 && !image_info->ping)
                 {    /*?? RotAngle=360-RotAngle;*/
                   Image
                     *flip_image;
@@ -1384,13 +1381,13 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                   /* Try to change CTM according to Flip - I am not sure, must be checked.
                      float_matrix Tx(3,3);
                      Tx(0,0)= 1;   Tx(1,0)= 0;   Tx(2,0)=0;
                      Tx(0,1)= 0;   Tx(1,1)=-1;   Tx(2,1)=0;
                      Tx(0,2)= 0;   Tx(1,2)=(WPG._2Rect.Y_ur+WPG._2Rect.Y_ll);
-                     Tx(2,2)=1; */      
-              }    
-    
+                     Tx(2,2)=1; */
+              }
+
 
               /* Allocate next image structure. */
               AcquireNextImage(image_info,image,exception);
               image->depth=8;
               if (image->next == (Image *) NULL)

Vulnerable code:         for (x=0; x < ((ssize_t) image->columns-1); x+=4)
            p++;
            if ((image->columns % 4) >= 1)

                if ((image->columns % 4) >= 2)

      break;     
                        AppendImageToList(&image,flip_image);    
    
      /* rotate command */
                        AppendImageToList(&image,rotate_image);    
                    }                
              image->columns=image->rows=0;
              image->rows=Bitmap2Header1.Height;  
                      BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);;
                  /* Try to change CTM according to Flip - I am not sure, must be checked.      
                     Tx(1,2)=0;   Tx(2,2)=1; */                  
                     Tx(2,2)=1; */      
              }    
    
Fixed code:         for (x=0; x < ((ssize_t) image->columns-3); x+=4)
            p++;
            if ((image->columns % 4) > 1)
                if ((image->columns % 4) > 2)
      break;
                        AppendImageToList(&image,flip_image);
                  /* rotate command */
                        AppendImageToList(&image,rotate_image);
                    }
              image->columns=image->rows=1;
              image->rows=Bitmap2Header1.Height;
                      BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
                  /* Try to change CTM according to Flip - I am not sure, must be checked.
                     Tx(1,2)=0;   Tx(2,2)=1; */
                     Tx(2,2)=1; */
              }