Index: GraphicsMagick-1.2.5/coders/rle.c
===================================================================
--- GraphicsMagick-1.2.5.orig/coders/rle.c	2017-05-31 11:22:50.074870586 +0200
+++ GraphicsMagick-1.2.5/coders/rle.c	2017-05-31 12:42:24.845375148 +0200
@@ -73,6 +73,18 @@
 %
 %
 */
+static size_t MagickArraySize(const size_t count, const size_t size)
+{
+  size_t
+    allocation_size;
+
+  allocation_size = size * count;
+  if ((count != 0) && (size != allocation_size/count))
+    allocation_size = 0;
+
+  return allocation_size;
+}
+
 static unsigned int IsRLE(const unsigned char *magick,const size_t length)
 {
   if (length < 2)
@@ -81,6 +93,55 @@ static unsigned int IsRLE(const unsigned
     return(True);
   return(False);
 }
+typedef struct _RLE_Header
+{
+  magick_uint8_t   Magic[2];    /* Magic number */
+  magick_uint16_t  Xpos;        /* Lower left x of image */
+  magick_uint16_t  Ypos;        /* Lower left y of image */
+  magick_uint16_t  XSize;       /* Image width */
+  magick_uint16_t  YSize;       /* Image height */
+  magick_uint8_t   Flags;       /* Misc flags */
+  magick_uint8_t   Ncolors;     /* Number of colors */
+  magick_uint8_t   Pixelbits;   /* Number of bits per channel */
+  magick_uint8_t   Ncmap;       /* Number of color channels in palette */
+  magick_uint8_t   Cmaplen;     /* Colormap length */
+
+} RLE_HEADER;
+
+static void LogRLEHeader(const RLE_HEADER* rle_header)
+{
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                        "RLE Header\n"
+                        "    Magic:     \\%03o\\%03o\n"
+                        "    Xpos:      %u\n"
+                        "    Ypos:      %u\n"
+                        "    XSize:     %u\n"
+                        "    YSize:     %u\n"
+                        "    Flags:     0x%02x (%u,%u,%u,%u,%u,%u,%u,%u)\n"
+                        "    Ncolors:   %u\n"
+                        "    Pixelbits: %u\n"
+                        "    Ncmap:     %u\n"
+                        "    Cmaplen:   %u",
+                        rle_header->Magic[0],
+                        rle_header->Magic[1],
+                        rle_header->Xpos,
+                        rle_header->Ypos,
+                        rle_header->XSize,
+                        rle_header->YSize,
+                        rle_header->Flags,
+                        (rle_header->Flags >> 7) & 0x01,
+                        (rle_header->Flags >> 6) & 0x01,
+                        (rle_header->Flags >> 5) & 0x01,
+                        (rle_header->Flags >> 4) & 0x01,
+                        (rle_header->Flags >> 3) & 0x01,
+                        (rle_header->Flags >> 2) & 0x01,
+                        (rle_header->Flags >> 1) & 0x01,
+                        (rle_header->Flags >> 0) & 0x01,
+                        rle_header->Ncolors,
+                        rle_header->Pixelbits,
+                        rle_header->Ncmap,
+                        rle_header->Cmaplen);
+}
 
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -113,6 +174,12 @@ static unsigned int IsRLE(const unsigned
 %
 %
 */
+#define ThrowRLEReaderException(code_,reason_,image_) \
+do { \
+  MagickFreeMemory(colormap); \
+  MagickFreeMemory(rle_pixels); \
+  ThrowReaderException(code_,reason_,image_); \
+} while (0);
 static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
 #define SkipLinesOp  0x01
@@ -122,8 +189,8 @@ static Image *ReadRLEImage(const ImageIn
 #define RunDataOp  0x06
 #define EOFOp  0x07
 
-  char
-    magick[12];
+  RLE_HEADER
+    rle_header;
 
   Image
     *image;
@@ -131,22 +198,23 @@ static Image *ReadRLEImage(const ImageIn
   int
     opcode,
     operand,
+    pixel,
     status;
 
-  long
+  unsigned long
     offset,
     y;
 
   register IndexPacket
     *indexes;
 
-  register long
+  register unsigned long
     x;
 
   register PixelPacket
     *q;
 
-  register long
+  register unsigned int
     i;
 
   register unsigned char
@@ -159,19 +227,16 @@ static Image *ReadRLEImage(const ImageIn
   size_t
     one;
 
+  unsigned int
+    map_length;
+
   unsigned char
     background_color[256],
-    *colormap,
-    pixel,
+    *colormap = (unsigned char *) NULL,
     plane,
-    *rle_pixels;
+    *rle_pixels = (unsigned char *) NULL;
 
   unsigned int
-    flags;
-
-  unsigned long
-    bits_per_pixel,
-    map_length,
     number_colormaps,
     number_pixels,
     number_planes,
@@ -188,45 +253,59 @@ static Image *ReadRLEImage(const ImageIn
   assert(image_info->signature == MagickSignature);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
+  (void) memset(&rle_header,0,sizeof(rle_header));
   image=AllocateImage(image_info);
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == False)
-    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
+    ThrowRLEReaderException(FileOpenError,UnableToOpenFile,image);
   /*
     Determine if this is a RLE file.
   */
-  count=ReadBlob(image,2,(char *) magick);
-  if ((count == 0) || (memcmp(magick,"\122\314",2) != 0))
-    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+  count=ReadBlob(image,2,(char *) &rle_header.Magic);
+  if ((count != 2) || (memcmp(&rle_header.Magic,"\122\314",2) != 0))
+    ThrowRLEReaderException(CorruptImageError,ImproperImageHeader,image);
   file_size=GetBlobSize(image);
   do
   {
     /*
       Read image header.
     */
-    (void) ReadBlobLSBShort(image);
-    (void) ReadBlobLSBShort(image);
-    image->columns=ReadBlobLSBShort(image);
-    image->rows=ReadBlobLSBShort(image);
-    flags=ReadBlobByte(image);
-    image->matte=flags & 0x04;
-    number_planes=ReadBlobByte(image);
-    bits_per_pixel=ReadBlobByte(image);
-    number_colormaps=ReadBlobByte(image);
-    map_length=(unsigned char) ReadBlobByte(image);
-    if (map_length >= 22)
-      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
-    one=1;
-    map_length=one << map_length;
-    if ((number_planes == 0) || (number_planes == 2) || (bits_per_pixel != 8) ||
-        (image->columns == 0))
-      ThrowReaderException(CoderError,DataEncodingSchemeIsNotSupported,image);
-    if (flags & 0x02)
+    rle_header.Xpos=ReadBlobLSBShort(image);
+    rle_header.Ypos=ReadBlobLSBShort(image);
+    rle_header.XSize=ReadBlobLSBShort(image);
+    rle_header.YSize=ReadBlobLSBShort(image);
+    rle_header.Flags=ReadBlobByte(image);
+    rle_header.Ncolors=ReadBlobByte(image);
+    rle_header.Pixelbits=ReadBlobByte(image);
+    rle_header.Ncmap=ReadBlobByte(image);
+    rle_header.Cmaplen=ReadBlobByte(image);
+    if (EOFBlob(image))
+      ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+
+    LogRLEHeader(&rle_header);
+
+    if ((rle_header.Ncolors == 0) ||
+        (rle_header.Ncolors == 2) ||
+        ((rle_header.Flags & 0x04) && (rle_header.Ncolors > 254)) ||
+        (rle_header.Pixelbits != 8))
+      ThrowRLEReaderException(CoderError,DataEncodingSchemeIsNotSupported,image);
+
+    if ((rle_header.XSize == 0) || (rle_header.YSize == 0))
+      ThrowRLEReaderException(CorruptImageError,ImproperImageHeader,image);
+
+    image->columns=rle_header.XSize;
+    image->rows=rle_header.YSize;
+    image->matte=rle_header.Flags & 0x04;
+    number_planes=rle_header.Ncolors;
+    number_colormaps=rle_header.Ncmap;
+    map_length=(1 << rle_header.Cmaplen);
+
+    if (rle_header.Flags & 0x02)
       {
         /*
           No background color-- initialize to black.
         */
-        for (i=0; i < (long) number_planes; i++)
+        for (i=0; i < number_planes; i++)
           background_color[i]=0;
         (void) ReadBlobByte(image);
       }
@@ -236,11 +315,15 @@ static Image *ReadRLEImage(const ImageIn
           Initialize background color.
         */
         p=background_color;
-        for (i=0; i < (long) number_planes; i++)
+        for (i=0; i < number_planes; i++)
           *p++=ReadBlobByte(image);
       }
     if ((number_planes & 0x01) == 0)
       (void) ReadBlobByte(image);
+
+    if (EOFBlob(image))
+      ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+
     if (image->matte)
       number_planes++;
 
@@ -249,10 +332,9 @@ static Image *ReadRLEImage(const ImageIn
     */
     if ((file_size == 0) ||
         ((((double) image->columns*image->rows*number_planes*
-           bits_per_pixel/8)/file_size) > 254.0))
-      ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,
-                           image);
-
+           rle_header.Pixelbits/8)/file_size) > 254.0))
+      ThrowRLEReaderException(CorruptImageError,InsufficientImageDataInFile,
+                              image);
     if ((double) number_colormaps*map_length > file_size)
       ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,
                            image);
@@ -266,11 +348,11 @@ static Image *ReadRLEImage(const ImageIn
         */
         colormap=MagickAllocateMemory(unsigned char *,3*number_colormaps*map_length);
         if (colormap == (unsigned char *) NULL)
-          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
+          ThrowRLEReaderException(ResourceLimitError,MemoryAllocationFailed,
             image);
         p=colormap; /* unsigned char * */
-        for (i=0; i < (long) number_colormaps; i++)
-          for (x=0; x < (long) map_length; x++)
+        for (i=0; i < number_colormaps; i++)
+          for (x=0; x < map_length; x++)
             {
               if (EOFBlob(image))
                 ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,
@@ -278,7 +360,7 @@ static Image *ReadRLEImage(const ImageIn
               *p++=(ReadBlobLSBShort(image) >> 8);
             }
       }
-    if (flags & 0x08)
+    if (rle_header.Flags & 0x08)
       {
         char
           *comment;
@@ -292,7 +374,7 @@ static Image *ReadRLEImage(const ImageIn
         length=ReadBlobLSBShort(image);
         comment=MagickAllocateMemory(char *,length);
         if (comment == (char *) NULL)
-          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
+          ThrowRLEReaderException(ResourceLimitError,MemoryAllocationFailed,
             image);
         (void) ReadBlob(image,length-1,comment);
         comment[length-1]='\0';
@@ -301,6 +383,10 @@ static Image *ReadRLEImage(const ImageIn
         if ((length & 0x01) == 0)
           (void) ReadBlobByte(image);
       }
+
+    if (EOFBlob(image))
+      ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+
     if (image_info->ping && (image_info->subrange != 0))
       if (image->scene >= (image_info->subimage+image_info->subrange-1))
         break;
@@ -316,26 +402,26 @@ static Image *ReadRLEImage(const ImageIn
       ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
     rle_pixels=MagickAllocateMemory(unsigned char *,image->columns*image->rows*Max(number_planes_filled,4));
     if (rle_pixels == (unsigned char *) NULL)
-      ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+      ThrowRLEReaderException(ResourceLimitError,MemoryAllocationFailed,image);
     rle_bytes=MagickArraySize(number_pixels,Max(number_planes,4));
     (void) memset(rle_pixels,0,rle_bytes);
-    if ((flags & 0x01) && !(flags & 0x02))
+    if ((rle_header.Flags & 0x01) && !(rle_header.Flags & 0x02))
       {
-        long
+        int
           j;
 
         /*
           Set background color.
         */
         p=rle_pixels;
-        for (i=0; i < (long) number_pixels; i++)
+        for (i=0; i < number_pixels; i++)
         {
           if (!image->matte)
-            for (j=0; j < (long) number_planes; j++)
+            for (j=0; j < (int) number_planes; j++)
               *p++=background_color[j];
           else
             {
-              for (j=0; j < (long) (number_planes-1); j++)
+              for (j=0; j < (int) (number_planes-1); j++)
                 *p++=background_color[j];
               *p++=0;  /* initialize matte channel */
             }
@@ -348,6 +434,8 @@ static Image *ReadRLEImage(const ImageIn
     x=0;
     y=0;
     opcode=ReadBlobByte(image);
+    if (opcode == EOF)
+      ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
     do
     {
       switch (opcode & 0x3f)
@@ -355,8 +443,14 @@ static Image *ReadRLEImage(const ImageIn
         case SkipLinesOp:
         {
           operand=ReadBlobByte(image);
+          if (operand == EOF)
+            ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
           if (opcode & 0x40)
-            operand=ReadBlobLSBShort(image);
+            {
+              operand=ReadBlobLSBShort(image);
+              if (EOFBlob(image))
+                ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+            }
           x=0;
           y+=operand;
           break;
@@ -364,6 +458,8 @@ static Image *ReadRLEImage(const ImageIn
         case SetColorOp:
         {
           operand=ReadBlobByte(image);
+          if (operand == EOF)
+            ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
           plane=(unsigned char) operand;
           if (plane == 255)
             plane=(unsigned char) (number_planes-1);
@@ -373,16 +469,28 @@ static Image *ReadRLEImage(const ImageIn
         case SkipPixelsOp:
         {
           operand=ReadBlobByte(image);
+          if (operand == EOF)
+            ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
           if (opcode & 0x40)
-            operand=ReadBlobLSBShort(image);
+          {
+             operand=ReadBlobLSBShort(image);
+             if (EOFBlob(image))
+               ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+          }
           x+=operand;
           break;
         }
         case ByteDataOp:
         {
           operand=ReadBlobByte(image);
+          if (operand == EOF)
+            ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
           if (opcode & 0x40)
+          {
             operand=ReadBlobLSBShort(image);
+            if (EOFBlob(image))
+              ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+          }
           offset=((image->rows-y-1)*image->columns*number_planes)+
             x*number_planes+plane;
           operand++;
@@ -395,11 +503,13 @@ static Image *ReadRLEImage(const ImageIn
             }
           p=rle_pixels+offset;
 
-          for (i=0; i < (long) operand; i++)
+          for (i=0; i < (unsigned int) operand; i++)
           {
             pixel=ReadBlobByte(image);
-            if ((y < (long) image->rows) && ((x+i) < (long) image->columns))
-              *p=pixel;
+            if (pixel == EOF)
+              ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+            if ((y < image->rows) && ((x+i) < image->columns))
+              *p=(unsigned char) pixel;
             p+=number_planes;
           }
           if (operand & 0x01)
@@ -410,9 +520,17 @@ static Image *ReadRLEImage(const ImageIn
         case RunDataOp:
         {
           operand=ReadBlobByte(image);
+          if (operand == EOF)
+            ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
           if (opcode & 0x40)
+          {
             operand=ReadBlobLSBShort(image);
+            if (EOFBlob(image))
+              ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+          }
           pixel=ReadBlobByte(image);
+          if (pixel == EOF)
+            ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
           (void) ReadBlobByte(image);
           operand++;
           offset=((image->rows-y-1)*image->columns*number_planes)+
@@ -425,7 +543,7 @@ static Image *ReadRLEImage(const ImageIn
               MagickFreeMemory(rle_pixels);
               ThrowReaderException(CorruptImageError,UnableToReadImageData,image);
             }
-          for (i=0; i < (long) operand; i++)
+          for (i=0; i < (unsigned int) operand; i++)
           {
             if ((y < (long) image->rows) && ((x+i) < (long) image->columns))
               *p=pixel;
@@ -438,6 +556,8 @@ static Image *ReadRLEImage(const ImageIn
           break;
       }
       opcode=ReadBlobByte(image);
+      if (opcode == EOF)
+        ThrowRLEReaderException(CorruptImageError,UnexpectedEndOfFile,image);
     } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
     if (number_colormaps != 0)
       {
@@ -453,7 +573,7 @@ static Image *ReadRLEImage(const ImageIn
         mask=(map_length-1);
         p=rle_pixels;
         if (number_colormaps == 1)
-          for (i=0; i < (long) number_pixels; i++)
+          for (i=0; i < number_pixels; i++)
           {
             index=MagickConstrainColormapIndex(image,*p & mask);
             *p=colormap[index];
@@ -461,8 +581,8 @@ static Image *ReadRLEImage(const ImageIn
           }
         else
           if ((number_planes >= 3) && (number_colormaps >= 3))
-            for (i=0; i < (long) number_pixels; i++)
-              for (x=0; x < (long) number_planes; x++)
+            for (i=0; i < number_pixels; i++)
+              for (x=0; x < number_planes; x++)
               {
                 index=MagickConstrainColormapIndex(image,x*map_length+(*p & mask));
                 *p=colormap[index];
@@ -478,12 +598,12 @@ static Image *ReadRLEImage(const ImageIn
           Convert raster image to DirectClass pixel packets.
         */
         p=rle_pixels;
-        for (y=0; y < (long) image->rows; y++)
+        for (y=0; y < image->rows; y++)
         {
           q=SetImagePixels(image,0,y,image->columns,1);
           if (q == (PixelPacket *) NULL)
             break;
-          for (x=0; x < (long) image->columns; x++)
+          for (x=0; x < image->columns; x++)
           {
             q->red=ScaleCharToQuantum(*p++);
             q->green=ScaleCharToQuantum(*p++);
@@ -508,11 +628,11 @@ static Image *ReadRLEImage(const ImageIn
         if (number_colormaps == 0)
           map_length=256;
         if (!AllocateImageColormap(image,map_length))
-          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
+          ThrowRLEReaderException(ResourceLimitError,MemoryAllocationFailed,
             image);
         p=colormap;
         if (number_colormaps == 1)
-          for (i=0; i < (long) image->colors; i++)
+          for (i=0; i < image->colors; i++)
           {
             /*
               Pseudocolor.
@@ -523,7 +643,7 @@ static Image *ReadRLEImage(const ImageIn
           }
         else
           if (number_colormaps > 1)
-            for (i=0; i < (long) image->colors; i++)
+            for (i=0; i < image->colors; i++)
             {
               image->colormap[i].red=ScaleCharToQuantum(*p);
               image->colormap[i].green=ScaleCharToQuantum(*(p+map_length));
@@ -536,7 +656,7 @@ static Image *ReadRLEImage(const ImageIn
             /*
               Convert raster image to PseudoClass pixel packets.
             */
-            for (y=0; y < (long) image->rows; y++)
+            for (y=0; y < image->rows; y++)
             {
               q=SetImagePixels(image,0,y,image->columns,1);
               if (q == (PixelPacket *) NULL)
@@ -558,12 +678,12 @@ static Image *ReadRLEImage(const ImageIn
             /*
               Image has a matte channel-- promote to DirectClass.
             */
-            for (y=0; y < (long) image->rows; y++)
+            for (y=0; y < image->rows; y++)
             {
               q=SetImagePixels(image,0,y,image->columns,1);
               if (q == (PixelPacket *) NULL)
                 break;
-              for (x=0; x < (long) image->columns; x++)
+              for (x=0; x < image->columns; x++)
               {
                 q->red=image->colormap[MagickConstrainColormapIndex(image,*p++)].red;
                 q->green=image->colormap[MagickConstrainColormapIndex(image,*p++)].green;
@@ -600,8 +720,8 @@ static Image *ReadRLEImage(const ImageIn
       if (image->scene >= (image_info->subimage+image_info->subrange-1))
         break;
     (void) ReadBlobByte(image);
-    count=ReadBlob(image,2,(char *) magick);
-    if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
+    count=ReadBlob(image,2,(char *) &rle_header.Magic);
+    if ((count == 2) && (memcmp(&rle_header.Magic,"\122\314",2) == 0))
       {
         /*
           Allocate next image structure.
@@ -616,7 +736,7 @@ static Image *ReadRLEImage(const ImageIn
         if (!MagickMonitor(LoadImagesText,TellBlob(image),GetBlobSize(image),exception))
           break;
       }
-  } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
+  } while ((count == 2) && (memcmp(&rle_header.Magic,"\122\314",2) == 0));
   while (image->previous != (Image *) NULL)
     image=image->previous;
   CloseBlob(image);
