Blob Blame History Raw
--- orig/coders/pcx.c	2013-04-07 20:20:50.000000000 +0400
+++ fixed/coders/pcx.c	2015-03-10 13:30:49.758099539 +0300
@@ -13,11 +13,11 @@
 %                Read/Write ZSoft IBM PC Paintbrush Image Format              %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
@@ -40,6 +40,7 @@
   Include declarations.
 */
 #include "magick/studio.h"
+#include "magick/attribute.h"
 #include "magick/blob.h"
 #include "magick/blob-private.h"
 #include "magick/cache.h"
@@ -220,6 +221,13 @@
 
 static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
+#define ThrowPCXException(severity,tag) \
+  { \
+    scanline=(unsigned char *) RelinquishMagickMemory(scanline); \
+    pixel_info=RelinquishVirtualMemory(pixel_info); \
+    ThrowReaderException(severity,tag); \
+  }
+
   Image
     *image;
 
@@ -235,6 +243,9 @@
     offset,
     *page_table;
 
+  MemoryInfo
+    *pixel_info;
+
   PCXInfo
     pcx_info;
 
@@ -264,8 +275,8 @@
 
   unsigned char
     packet,
-    *pcx_colormap,
-    *pcx_pixels,
+    pcx_colormap[768],
+    *pixels,
     *scanline;
 
   /*
@@ -317,10 +328,12 @@
       if (offset < 0)
         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
     }
-  pcx_colormap=(unsigned char *) NULL;
   count=ReadBlob(image,1,&pcx_info.identifier);
   for (id=1; id < 1024; id++)
   {
+    int
+      bits_per_pixel;
+
     /*
       Verify PCX identifier.
     */
@@ -328,7 +341,10 @@
     if ((count == 0) || (pcx_info.identifier != 0x0a))
       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
     pcx_info.encoding=(unsigned char) ReadBlobByte(image);
-    pcx_info.bits_per_pixel=(unsigned char) ReadBlobByte(image);
+    bits_per_pixel=ReadBlobByte(image);
+    if (bits_per_pixel == -1)
+      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+    pcx_info.bits_per_pixel=(unsigned char) bits_per_pixel;
     pcx_info.left=ReadBlobLSBShort(image);
     pcx_info.top=ReadBlobLSBShort(image);
     pcx_info.right=ReadBlobLSBShort(image);
@@ -350,13 +366,11 @@
     image->x_resolution=(double) pcx_info.horizontal_resolution;
     image->y_resolution=(double) pcx_info.vertical_resolution;
     image->colors=16;
-    pcx_colormap=(unsigned char *) AcquireQuantumMemory(256UL,
-      3*sizeof(*pcx_colormap));
-    if (pcx_colormap == (unsigned char *) NULL)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
     count=ReadBlob(image,3*image->colors,pcx_colormap);
     pcx_info.reserved=(unsigned char) ReadBlobByte(image);
     pcx_info.planes=(unsigned char) ReadBlobByte(image);
+    if ((pcx_info.bits_per_pixel*pcx_info.planes) >= 64)
+      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
     one=1;
     if ((pcx_info.bits_per_pixel != 8) || (pcx_info.planes == 1))
       if ((pcx_info.version == 3) || (pcx_info.version == 5) ||
@@ -384,25 +398,33 @@
     /*
       Read image data.
     */
-    pcx_packets=(size_t) image->rows*pcx_info.bytes_per_line*
-      pcx_info.planes;
-    pcx_pixels=(unsigned char *) AcquireQuantumMemory(pcx_packets,
-      sizeof(*pcx_pixels));
+    pcx_packets=(size_t) image->rows*pcx_info.bytes_per_line*pcx_info.planes;
+    if ((size_t) (pcx_info.bits_per_pixel*pcx_info.planes*image->columns) >
+        (pcx_packets*8U))
+      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
     scanline=(unsigned char *) AcquireQuantumMemory(MagickMax(image->columns,
       pcx_info.bytes_per_line),MagickMax(8,pcx_info.planes)*sizeof(*scanline));
-    if ((pcx_pixels == (unsigned char *) NULL) ||
-        (scanline == (unsigned char *) NULL))
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+    pixel_info=AcquireVirtualMemory(pcx_packets,sizeof(*pixels));
+    if ((scanline == (unsigned char *) NULL) ||
+        (pixel_info == (MemoryInfo *) NULL))
+      {
+        if (scanline != (unsigned char *) NULL)
+          scanline=(unsigned char *) RelinquishMagickMemory(scanline);
+        if (pixel_info != (MemoryInfo *) NULL)
+          pixel_info=RelinquishVirtualMemory(pixel_info);
+        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      }
+    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
     /*
       Uncompress image data.
     */
-    p=pcx_pixels;
+    p=pixels;
     if (pcx_info.encoding == 0)
       while (pcx_packets != 0)
       {
         packet=(unsigned char) ReadBlobByte(image);
         if (EOFBlob(image) != MagickFalse)
-          ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
+          ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile");
         *p++=packet;
         pcx_packets--;
       }
@@ -411,7 +433,7 @@
       {
         packet=(unsigned char) ReadBlobByte(image);
         if (EOFBlob(image) != MagickFalse)
-          ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
+          ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile");
         if ((packet & 0xc0) != 0xc0)
           {
             *p++=packet;
@@ -421,7 +443,7 @@
         count=(ssize_t) (packet & 0x3f);
         packet=(unsigned char) ReadBlobByte(image);
         if (EOFBlob(image) != MagickFalse)
-          ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
+          ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile");
         for ( ; count != 0; count--)
         {
           *p++=packet;
@@ -440,7 +462,7 @@
             Initialize image colormap.
           */
           if (image->colors > 256)
-            ThrowReaderException(CorruptImageError,"ColormapExceeds256Colors");
+            ThrowPCXException(CorruptImageError,"ColormapExceeds256Colors");
           if ((pcx_info.bits_per_pixel*pcx_info.planes) == 1)
             {
               /*
@@ -469,14 +491,13 @@
                   image->colormap[i].blue=ScaleCharToQuantum(*p++);
                 }
             }
-          pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
         }
     /*
       Convert PCX raster image to pixel packets.
     */
     for (y=0; y < (ssize_t) image->rows; y++)
     {
-      p=pcx_pixels+(y*pcx_info.bytes_per_line*pcx_info.planes);
+      p=pixels+(y*pcx_info.bytes_per_line*pcx_info.planes);
       q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
       if (q == (PixelPacket *) NULL)
         break;
@@ -626,9 +647,7 @@
     if (image->storage_class == PseudoClass)
       (void) SyncImage(image);
     scanline=(unsigned char *) RelinquishMagickMemory(scanline);
-    if (pcx_colormap != (unsigned char *) NULL)
-      pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
-    pcx_pixels=(unsigned char *) RelinquishMagickMemory(pcx_pixels);
+    pixel_info=RelinquishVirtualMemory(pixel_info);
     if (EOFBlob(image) != MagickFalse)
       {
         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
@@ -839,6 +858,9 @@
     *page_table,
     scene;
 
+  MemoryInfo
+    *pixel_info;
+
   PCXInfo
     pcx_info;
 
@@ -863,7 +885,7 @@
 
   unsigned char
     *pcx_colormap,
-    *pcx_pixels;
+    *pixels;
 
   /*
     Open output image file.
@@ -877,8 +899,7 @@
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
   if (status == MagickFalse)
     return(status);
-  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
-    (void) TransformImageColorspace(image,sRGBColorspace);
+  (void) TransformImageColorspace(image,sRGBColorspace);
   page_table=(MagickOffsetType *) NULL;
   if ((LocaleCompare(image_info->magick,"DCX") == 0) ||
       ((GetNextImageInList(image) != (Image *) NULL) &&
@@ -982,29 +1003,24 @@
     for (i=0; i < 58; i++)
       (void) WriteBlobByte(image,'\0');
     length=(size_t) pcx_info.bytes_per_line;
-    pcx_pixels=(unsigned char *) AcquireQuantumMemory(length,pcx_info.planes*
-      sizeof(*pcx_pixels));
-    if (pcx_pixels == (unsigned char *) NULL)
+    pixel_info=AcquireVirtualMemory(length,pcx_info.planes*sizeof(*pixels));
+    if (pixel_info == (MemoryInfo *) NULL)
       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
-    q=pcx_pixels;
+    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
+    q=pixels;
     if ((image->storage_class == DirectClass) || (image->colors > 256))
       {
-        const PixelPacket
-          *pixels;
-
         /*
           Convert DirectClass image to PCX raster pixels.
         */
         for (y=0; y < (ssize_t) image->rows; y++)
         {
-          pixels=GetVirtualPixels(image,0,y,image->columns,1,
-            &image->exception);
-          if (pixels == (const PixelPacket *) NULL)
-            break;
-          q=pcx_pixels;
+          q=pixels;
           for (i=0; i < pcx_info.planes; i++)
           {
-            p=pixels;
+            p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+            if (p == (const PixelPacket *) NULL)
+              break;
             switch ((int) i)
             {
               case 0:
@@ -1047,7 +1063,7 @@
               }
             }
           }
-          if (PCXWritePixels(&pcx_info,pcx_pixels,image) == MagickFalse)
+          if (PCXWritePixels(&pcx_info,pixels,image) == MagickFalse)
             break;
           if (image->previous == (Image *) NULL)
             {
@@ -1067,10 +1083,10 @@
             if (p == (const PixelPacket *) NULL)
               break;
             indexes=GetVirtualIndexQueue(image);
-            q=pcx_pixels;
+            q=pixels;
             for (x=0; x < (ssize_t) image->columns; x++)
               *q++=(unsigned char) GetPixelIndex(indexes+x);
-            if (PCXWritePixels(&pcx_info,pcx_pixels,image) == MagickFalse)
+            if (PCXWritePixels(&pcx_info,pixels,image) == MagickFalse)
               break;
             if (image->previous == (Image *) NULL)
               {
@@ -1082,9 +1098,6 @@
           }
         else
           {
-            IndexPacket
-              polarity;
-
             register unsigned char
               bit,
               byte;
@@ -1092,26 +1105,19 @@
             /*
               Convert PseudoClass image to a PCX monochrome image.
             */
-            polarity=(IndexPacket) (GetPixelLuma(image,
-              &image->colormap[0]) < (QuantumRange/2) ? 1 : 0);
-            if (image->colors == 2)
-              polarity=(IndexPacket) (
-                GetPixelLuma(image,&image->colormap[0]) <
-                GetPixelLuma(image,&image->colormap[1]) ? 1 : 0);
             for (y=0; y < (ssize_t) image->rows; y++)
             {
-              p=GetVirtualPixels(image,0,y,image->columns,1,
-                &image->exception);
+              p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
               if (p == (const PixelPacket *) NULL)
                 break;
               indexes=GetVirtualIndexQueue(image);
               bit=0;
               byte=0;
-              q=pcx_pixels;
+              q=pixels;
               for (x=0; x < (ssize_t) image->columns; x++)
               {
                 byte<<=1;
-                if (GetPixelIndex(indexes+x) == polarity)
+                if (GetPixelLuma(image,p) >= (QuantumRange/2.0))
                   byte|=0x01;
                 bit++;
                 if (bit == 8)
@@ -1124,7 +1130,7 @@
               }
               if (bit != 0)
                 *q++=byte << (8-bit);
-              if (PCXWritePixels(&pcx_info,pcx_pixels,image) == MagickFalse)
+              if (PCXWritePixels(&pcx_info,pixels,image) == MagickFalse)
                 break;
               if (image->previous == (Image *) NULL)
                 {
@@ -1138,7 +1144,7 @@
         (void) WriteBlobByte(image,pcx_info.colormap_signature);
         (void) WriteBlob(image,3*256,pcx_colormap);
       }
-    pcx_pixels=(unsigned char *) RelinquishMagickMemory(pcx_pixels);
+    pixel_info=RelinquishVirtualMemory(pixel_info);
     pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
     if (page_table == (MagickOffsetType *) NULL)
       break;