]> granicus.if.org Git - imagemagick/blobdiff - coders/pcx.c
Use memset() rather than ResetMagickMemory()
[imagemagick] / coders / pcx.c
index 8505d50c3082de583f5ea2d8f1856c5e96d43efe..a8bce12458d9bd14b0912e4542ae92696662ff86 100644 (file)
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2018 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  %
 %  obtain a copy of the License at                                            %
 %                                                                             %
-%    http://www.imagemagick.org/script/license.php                            %
+%    https://www.imagemagick.org/script/license.php                           %
 %                                                                             %
 %  Unless required by applicable law or agreed to in writing, software        %
 %  distributed under the License is distributed on an "AS IS" BASIS,          %
@@ -56,6 +56,7 @@
 #include "MagickCore/list.h"
 #include "MagickCore/magick.h"
 #include "MagickCore/memory_.h"
+#include "MagickCore/memory-private.h"
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/pixel-accessor.h"
@@ -202,11 +203,15 @@ static MagickBooleanType IsPCX(const unsigned char *magick,const size_t length)
 static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
 #define ThrowPCXException(severity,tag) \
-  { \
+{ \
+  if (scanline != (unsigned char *) NULL) \
     scanline=(unsigned char *) RelinquishMagickMemory(scanline); \
+  if (pixel_info != (MemoryInfo *) NULL) \
     pixel_info=RelinquishVirtualMemory(pixel_info); \
-    ThrowReaderException(severity,tag); \
-  }
+  if (page_table != (MagickOffsetType *) NULL) \
+    page_table=(MagickOffsetType *) RelinquishMagickMemory(page_table); \
+  ThrowReaderException(severity,tag); \
+}
 
   Image
     *image;
@@ -260,12 +265,12 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     Open image file.
   */
   assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
+  assert(image_info->signature == MagickCoreSignature);
   if (image_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       image_info->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   image=AcquireImage(image_info,exception);
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
@@ -277,6 +282,8 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     Determine if this a PCX file.
   */
   page_table=(MagickOffsetType *) NULL;
+  scanline=(unsigned char *) NULL;
+  pixel_info=(MemoryInfo *) NULL;
   if (LocaleCompare(image_info->magick,"DCX") == 0)
     {
       size_t
@@ -287,11 +294,11 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
       */
       magic=ReadBlobLSBLong(image);
       if (magic != 987654321)
-        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+        ThrowPCXException(CorruptImageError,"ImproperImageHeader");
       page_table=(MagickOffsetType *) AcquireQuantumMemory(1024UL,
         sizeof(*page_table));
       if (page_table == (MagickOffsetType *) NULL)
-        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        ThrowPCXException(ResourceLimitError,"MemoryAllocationFailed");
       for (id=0; id < 1024; id++)
       {
         page_table[id]=(MagickOffsetType) ReadBlobLSBLong(image);
@@ -303,7 +310,7 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     {
       offset=SeekBlob(image,(MagickOffsetType) page_table[0],SEEK_SET);
       if (offset < 0)
-        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+        ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     }
   count=ReadBlob(image,1,&pcx_info.identifier);
   for (id=1; id < 1024; id++)
@@ -316,11 +323,11 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     */
     pcx_info.version=(unsigned char) ReadBlobByte(image);
     if ((count != 1) || (pcx_info.identifier != 0x0a))
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     pcx_info.encoding=(unsigned char) ReadBlobByte(image);
     bits_per_pixel=ReadBlobByte(image);
     if (bits_per_pixel == -1)
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     pcx_info.bits_per_pixel=(unsigned char) bits_per_pixel;
     pcx_info.left=ReadBlobLSBShort(image);
     pcx_info.top=ReadBlobLSBShort(image);
@@ -336,23 +343,33 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     image->rows=(size_t) MagickAbsoluteValue((ssize_t) pcx_info.bottom-
       pcx_info.top)+1UL;
     if ((image->columns == 0) || (image->rows == 0) ||
-        ((pcx_info.bits_per_pixel != 1) &&
-         (pcx_info.bits_per_pixel != 2) &&
-         (pcx_info.bits_per_pixel != 4) &&
-         (pcx_info.bits_per_pixel != 8)))
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+        ((pcx_info.bits_per_pixel != 1) && (pcx_info.bits_per_pixel != 2) &&
+         (pcx_info.bits_per_pixel != 4) && (pcx_info.bits_per_pixel != 8)))
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     image->depth=pcx_info.bits_per_pixel;
     image->units=PixelsPerInchResolution;
     image->resolution.x=(double) pcx_info.horizontal_resolution;
     image->resolution.y=(double) pcx_info.vertical_resolution;
     image->colors=16;
+    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
+      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
+        break;
+    status=SetImageExtent(image,image->columns,image->rows,exception);
+    if (status == MagickFalse)
+      ThrowPCXException(exception->severity,exception->reason);
+    (void) SetImageBackgroundColor(image,exception);
+    (void) memset(pcx_colormap,0,sizeof(pcx_colormap));
     count=ReadBlob(image,3*image->colors,pcx_colormap);
     if (count != (ssize_t) (3*image->colors))
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     pcx_info.reserved=(unsigned char) ReadBlobByte(image);
     pcx_info.planes=(unsigned char) ReadBlobByte(image);
+    if (pcx_info.planes == 0)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    if (pcx_info.planes > 6)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     if ((pcx_info.bits_per_pixel*pcx_info.planes) >= 64)
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     one=1;
     if ((pcx_info.bits_per_pixel != 8) || (pcx_info.planes == 1))
       if ((pcx_info.version == 3) || (pcx_info.version == 5) ||
@@ -360,7 +377,7 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
         image->colors=(size_t) MagickMin(one << (1UL*
           (pcx_info.bits_per_pixel*pcx_info.planes)),256UL);
     if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      ThrowPCXException(ResourceLimitError,"MemoryAllocationFailed");
     if ((pcx_info.bits_per_pixel >= 8) && (pcx_info.planes != 1))
       image->storage_class=DirectClass;
     p=pcx_colormap;
@@ -376,19 +393,18 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     pcx_info.vertical_screensize=ReadBlobLSBShort(image);
     for (i=0; i < 54; i++)
       (void) ReadBlobByte(image);
-    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
-      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
-        break;
-    status=SetImageExtent(image,image->columns,image->rows,exception);
-    if (status == MagickFalse)
-      return(DestroyImageList(image));
     /*
       Read image data.
     */
-    pcx_packets=(size_t) image->rows*pcx_info.bytes_per_line*pcx_info.planes;
+    if (HeapOverflowSanityCheck(image->rows, (size_t) pcx_info.bytes_per_line) != MagickFalse)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    pcx_packets=(size_t) image->rows*pcx_info.bytes_per_line;
+    if (HeapOverflowSanityCheck(pcx_packets, (size_t) pcx_info.planes) != MagickFalse)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    pcx_packets=(size_t) pcx_packets*pcx_info.planes;
     if ((size_t) (pcx_info.bits_per_pixel*pcx_info.planes*image->columns) >
         (pcx_packets*8U))
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     scanline=(unsigned char *) AcquireQuantumMemory(MagickMax(image->columns,
       pcx_info.bytes_per_line),MagickMax(8,pcx_info.planes)*sizeof(*scanline));
     pixel_info=AcquireVirtualMemory(pcx_packets,2*sizeof(*pixels));
@@ -399,9 +415,12 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
           scanline=(unsigned char *) RelinquishMagickMemory(scanline);
         if (pixel_info != (MemoryInfo *) NULL)
           pixel_info=RelinquishVirtualMemory(pixel_info);
-        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        ThrowPCXException(ResourceLimitError,"MemoryAllocationFailed");
       }
+    (void) memset(scanline,0,(size_t) MagickMax(image->columns,
+      pcx_info.bytes_per_line)*MagickMax(8,pcx_info.planes)*sizeof(*scanline));
     pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
+    (void) memset(pixels,0,(size_t) pcx_packets*(2*sizeof(*pixels)));
     /*
       Uncompress image data.
     */
@@ -653,7 +672,7 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
       break;
     offset=SeekBlob(image,(MagickOffsetType) page_table[id],SEEK_SET);
     if (offset < 0)
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     count=ReadBlob(image,1,&pcx_info.identifier);
     if ((count != 0) && (pcx_info.identifier == 0x0a))
       {
@@ -707,22 +726,20 @@ ModuleExport size_t RegisterPCXImage(void)
   MagickInfo
     *entry;
 
-  entry=SetMagickInfo("DCX");
+  entry=AcquireMagickInfo("PCX","DCX","ZSoft IBM PC multi-page Paintbrush");
   entry->decoder=(DecodeImageHandler *) ReadPCXImage;
   entry->encoder=(EncodeImageHandler *) WritePCXImage;
-  entry->flags|=CoderSeekableStreamFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
+  entry->flags|=CoderEncoderSeekableStreamFlag;
   entry->magick=(IsImageFormatHandler *) IsDCX;
-  entry->description=ConstantString("ZSoft IBM PC multi-page Paintbrush");
-  entry->module=ConstantString("PCX");
   (void) RegisterMagickInfo(entry);
-  entry=SetMagickInfo("PCX");
+  entry=AcquireMagickInfo("PCX","PCX","ZSoft IBM PC Paintbrush");
   entry->decoder=(DecodeImageHandler *) ReadPCXImage;
   entry->encoder=(EncodeImageHandler *) WritePCXImage;
   entry->magick=(IsImageFormatHandler *) IsPCX;
   entry->flags^=CoderAdjoinFlag;
-  entry->flags|=CoderSeekableStreamFlag;
-  entry->description=ConstantString("ZSoft IBM PC Paintbrush");
-  entry->module=ConstantString("PCX");
+  entry->flags|=CoderDecoderSeekableStreamFlag;
+  entry->flags|=CoderEncoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);
 }
@@ -879,16 +896,18 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image,
     Open output image file.
   */
   assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
+  assert(image_info->signature == MagickCoreSignature);
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   if (status == MagickFalse)
     return(status);
+  if ((image->columns > 65535UL) || (image->rows > 65535UL))
+    ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
   (void) TransformImageColorspace(image,sRGBColorspace,exception);
   page_table=(MagickOffsetType *) NULL;
   if ((LocaleCompare(image_info->magick,"DCX") == 0) ||
@@ -952,8 +971,10 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image,
         if (image->alpha_trait != UndefinedPixelTrait)
           pcx_info.planes++;
       }
-    pcx_info.bytes_per_line=(unsigned short) (((size_t) image->columns*
-      pcx_info.bits_per_pixel+7)/8);
+    length=(((size_t) image->columns*pcx_info.bits_per_pixel+7)/8);
+    if (length > 65535UL)
+      ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
+    pcx_info.bytes_per_line=(unsigned short) length;
     pcx_info.palette_info=1;
     pcx_info.colormap_signature=0x0c;
     /*
@@ -995,7 +1016,12 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image,
     length=(size_t) pcx_info.bytes_per_line;
     pixel_info=AcquireVirtualMemory(length,pcx_info.planes*sizeof(*pixels));
     if (pixel_info == (MemoryInfo *) NULL)
-      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+      {
+        pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
+        if (page_table != (MagickOffsetType *) NULL)
+          page_table=(MagickOffsetType *) RelinquishMagickMemory(page_table);
+        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+      }
     pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
     q=pixels;
     if ((image->storage_class == DirectClass) || (image->colors > 256))
@@ -1081,8 +1107,8 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image,
               break;
             if (image->previous == (Image *) NULL)
               {
-                status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
-                image->rows);
+                status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
+                  y,image->rows);
                 if (status == MagickFalse)
                   break;
               }
@@ -1156,7 +1182,10 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image,
       page_table[scene+1]=0;
       offset=SeekBlob(image,0L,SEEK_SET);
       if (offset < 0)
-        ThrowWriterException(CorruptImageError,"ImproperImageHeader");
+        {
+          page_table=(MagickOffsetType *) RelinquishMagickMemory(page_table);
+          ThrowWriterException(CorruptImageError,"ImproperImageHeader");
+        }
       (void) WriteBlobLSBLong(image,0x3ADE68B1L);
       for (i=0; i <= (ssize_t) scene; i++)
         (void) WriteBlobLSBLong(image,(unsigned int) page_table[i]);