]> granicus.if.org Git - imagemagick/blobdiff - coders/palm.c
https://github.com/ImageMagick/ImageMagick/issues/631
[imagemagick] / coders / palm.c
index 97d201c1ce8500b6968c2f1ccc450caefd2a90c9..6283f3f945e83d36bf0a8451e0d1566dd95f5ce5 100644 (file)
@@ -23,7 +23,7 @@
 %  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,          %
@@ -89,7 +89,7 @@
 /*
  The 256 color system palette for Palm Computing Devices.
 */
-static unsigned char
+static const unsigned char
   PalmPalette[256][3] =
   {
     {255, 255,255}, {255, 204,255}, {255, 153,255}, {255, 102,255},
@@ -229,21 +229,6 @@ static ssize_t FindColor(PixelInfo *packet)
 %    o exception: return any errors or warnings in this structure.
 %
 */
-
-static inline size_t MagickMax(const size_t x,const size_t y)
-{
-  if (x > y)
-    return(x);
-  return(y);
-}
-
-static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
-{
-  if (x < y)
-    return(x);
-  return(y);
-}
-
 static Image *ReadPALMImage(const ImageInfo *image_info,
   ExceptionInfo *exception)
 {
@@ -270,10 +255,6 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
   register Quantum
     *q;
 
-  ssize_t
-    count,
-    y;
-
   size_t
     bytes_per_row,
     flags,
@@ -292,8 +273,12 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
     size,
     bit;
 
+  ssize_t
+    count,
+    y;
+
   unsigned char
-    *lastrow,
+    *last_row,
     *one_row,
     *ptr;
 
@@ -304,12 +289,12 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
     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)
@@ -332,13 +317,20 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
     bytes_per_row=ReadBlobMSBShort(image);
     flags=ReadBlobMSBShort(image);
     bits_per_pixel=(size_t) ReadBlobByte(image);
-    if ((bits_per_pixel == 0) || (bits_per_pixel > 16))
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+    if ((bits_per_pixel != 1) && (bits_per_pixel != 2) &&
+        (bits_per_pixel != 4) && (bits_per_pixel != 8) &&
+        (bits_per_pixel != 16))
+      ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
     version=(size_t) ReadBlobByte(image);
-    (void) version;
+    if ((version != 0) && (version != 1) && (version != 2))
+      ThrowReaderException(CorruptImageError,"FileFormatVersionMismatch");
     nextDepthOffset=(size_t) ReadBlobMSBShort(image);
     transparentIndex=(size_t) ReadBlobByte(image);
     compressionType=(size_t) ReadBlobByte(image);
+    if ((compressionType != PALM_COMPRESSION_NONE) &&
+        (compressionType != PALM_COMPRESSION_SCANLINE ) &&
+        (compressionType != PALM_COMPRESSION_RLE))
+      ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
     pad=ReadBlobMSBShort(image);
     (void) pad;
     /*
@@ -384,17 +376,15 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
           }
         }
       else
+        for (i=0; i < (ssize_t) (1L << bits_per_pixel); i++)
         {
-          for (i=0; i < (ssize_t) (1L << bits_per_pixel); i++)
-          {
-            index=ConstrainColormapIndex(image,255-i,exception);
-            image->colormap[index].red=(MagickRealType)
-              ScaleCharToQuantum(PalmPalette[i][0]);
-            image->colormap[index].green=(MagickRealType)
-              ScaleCharToQuantum(PalmPalette[i][1]);
-            image->colormap[index].blue=(MagickRealType)
-              ScaleCharToQuantum(PalmPalette[i][2]);
-          }
+          index=ConstrainColormapIndex(image,255-i,exception);
+          image->colormap[index].red=(MagickRealType)
+            ScaleCharToQuantum(PalmPalette[i][0]);
+          image->colormap[index].green=(MagickRealType)
+            ScaleCharToQuantum(PalmPalette[i][1]);
+          image->colormap[index].blue=(MagickRealType)
+            ScaleCharToQuantum(PalmPalette[i][2]);
         }
       }
     if (flags & PALM_IS_COMPRESSED_FLAG)
@@ -406,25 +396,36 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
         image->storage_class=PseudoClass;
         image->depth=8;
       }
+    if (image_info->ping != MagickFalse)
+      {
+        (void) CloseBlob(image);
+        return(image);
+      }
+    status=SetImageExtent(image,image->columns,image->rows,exception);
+    if (status == MagickFalse)
+      return(DestroyImageList(image));
     one_row=(unsigned char *) AcquireQuantumMemory(MagickMax(bytes_per_row,
       2*image->columns),sizeof(*one_row));
     if (one_row == (unsigned char *) NULL)
       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-    lastrow=(unsigned char *) NULL;
-    if (compressionType == PALM_COMPRESSION_SCANLINE) {
-      lastrow=(unsigned char *) AcquireQuantumMemory(MagickMax(bytes_per_row,
-        2*image->columns),sizeof(*lastrow));
-    if (lastrow == (unsigned char *) NULL)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-    }
+    last_row=(unsigned char *) NULL;
+    if (compressionType == PALM_COMPRESSION_SCANLINE)
+      {
+        last_row=(unsigned char *) AcquireQuantumMemory(MagickMax(bytes_per_row,
+          2*image->columns),sizeof(*last_row));
+        if (last_row == (unsigned char *) NULL)
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      }
     mask=(size_t) (1U << bits_per_pixel)-1;
-    for (y = 0; y < (ssize_t) image->rows; y++)
+    for (y=0; y < (ssize_t) image->rows; y++)
     {
       if ((flags & PALM_IS_COMPRESSED_FLAG) == 0)
         {
           /* TODO move out of loop! */
           image->compression=NoCompression;
           count=ReadBlob(image,bytes_per_row,one_row);
+          if (count != (ssize_t) bytes_per_row)
+            break;
         }
       else
         {
@@ -435,6 +436,8 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
               for (i=0; i < (ssize_t) bytes_per_row; )
               {
                 count=(ssize_t) ReadBlobByte(image);
+                if (count < 0)
+                  break;
                 count=MagickMin(count,(ssize_t) bytes_per_row-i);
                 byte=(size_t) ReadBlobByte(image);
                 (void) ResetMagickMemory(one_row+i,(int) byte,(size_t) count);
@@ -453,16 +456,18 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
               for (i=0; i < (ssize_t) bytes_per_row; i+=8)
               {
                 count=(ssize_t) ReadBlobByte(image);
+                if (count < 0)
+                  break;
                 byte=(size_t) MagickMin((ssize_t) bytes_per_row-i,8);
                 for (bit=0; bit < byte; bit++)
                 {
                   if ((y == 0) || (count & (one << (7 - bit))))
                     one_row[i+bit]=(unsigned char) ReadBlobByte(image);
                   else
-                    one_row[i+bit]=lastrow[i+bit];
+                    one_row[i+bit]=last_row[i+bit];
                 }
               }
-              (void) CopyMagickMemory(lastrow, one_row, bytes_per_row);
+              (void) CopyMagickMemory(last_row, one_row, bytes_per_row);
             }
         }
       ptr=one_row;
@@ -472,7 +477,12 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
       if (bits_per_pixel == 16)
         {
           if (image->columns > (2*bytes_per_row))
-            ThrowReaderException(CorruptImageError,"CorruptImage");
+            {
+              one_row=(unsigned char *) RelinquishMagickMemory(one_row);
+              if (compressionType == PALM_COMPRESSION_SCANLINE)
+                last_row=(unsigned char *) RelinquishMagickMemory(last_row);
+              ThrowReaderException(CorruptImageError,"CorruptImage");
+            }
           for (x=0; x < (ssize_t) image->columns; x++)
           {
             color16=(*ptr++ << 8);
@@ -493,10 +503,15 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
           for (x=0; x < (ssize_t) image->columns; x++)
           {
             if ((size_t) (ptr-one_row) >= bytes_per_row)
-              ThrowReaderException(CorruptImageError,"CorruptImage");
+              {
+                one_row=(unsigned char *) RelinquishMagickMemory(one_row);
+                if (compressionType == PALM_COMPRESSION_SCANLINE)
+                  last_row=(unsigned char *) RelinquishMagickMemory(last_row);
+                ThrowReaderException(CorruptImageError,"CorruptImage");
+              }
             index=(Quantum) (mask-(((*ptr) & (mask << bit)) >> bit));
             SetPixelIndex(image,index,q);
-            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+            SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
             if (bit)
               bit-=bits_per_pixel;
             else
@@ -519,14 +534,22 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
       }
     if (flags & PALM_HAS_TRANSPARENCY_FLAG)
       {
+        ssize_t index=ConstrainColormapIndex(image,(ssize_t) (mask-
+          transparentIndex),exception);
         if (bits_per_pixel != 16)
-          transpix=image->colormap[mask-transparentIndex];
+          transpix=image->colormap[index];
         (void) TransparentPaintImage(image,&transpix,(Quantum) TransparentAlpha,
           MagickFalse,exception);
       }
     one_row=(unsigned char *) RelinquishMagickMemory(one_row);
     if (compressionType == PALM_COMPRESSION_SCANLINE)
-      lastrow=(unsigned char *) RelinquishMagickMemory(lastrow);
+      last_row=(unsigned char *) RelinquishMagickMemory(last_row);
+    if (EOFBlob(image) != MagickFalse)
+      {
+        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
+          image->filename);
+        break;
+      }
     /*
       Proceed to next image. Copied from coders/pnm.c
     */
@@ -540,13 +563,9 @@ static Image *ReadPALMImage(const ImageInfo *image_info,
         */
         totalOffset+=(MagickOffsetType) (nextDepthOffset*4);
         if (totalOffset >= (MagickOffsetType) GetBlobSize(image))
-          {
-            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
-          }
+          ThrowReaderException(CorruptImageError,"ImproperImageHeader")
         else
-          {
-            seekNextDepth=SeekBlob(image,totalOffset,SEEK_SET);
-          }
+          seekNextDepth=SeekBlob(image,totalOffset,SEEK_SET);
         if (seekNextDepth != totalOffset)
           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
         /*
@@ -596,12 +615,11 @@ ModuleExport size_t RegisterPALMImage(void)
   MagickInfo
     *entry;
 
-  entry=SetMagickInfo("PALM");
+  entry=AcquireMagickInfo("PALM","PALM","Palm pixmap");
   entry->decoder=(DecodeImageHandler *) ReadPALMImage;
   entry->encoder=(EncodeImageHandler *) WritePALMImage;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Palm pixmap");
-  entry->module=ConstantString("PALM");
+  entry->flags|=CoderDecoderSeekableStreamFlag;
+  entry->flags|=CoderEncoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);
 }
@@ -700,7 +718,7 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
     bit,
     byte,
     color,
-    *lastrow,
+    *last_row,
     *one_row,
     *ptr,
     version;
@@ -716,13 +734,13 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
     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);
@@ -742,10 +760,11 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
     (void) TransformImageColorspace(image,sRGBColorspace,exception);
     count=GetNumberColors(image,NULL,exception);
     for (bits_per_pixel=1;  (one << bits_per_pixel) < count; bits_per_pixel*=2) ;
-    if (image_info->depth > 100)
-      bits_per_pixel=image_info->depth-100;
-    if (bits_per_pixel < 16)
-      (void) TransformImageColorspace(image,image->colorspace,exception);
+    if (bits_per_pixel > 16)
+      bits_per_pixel=16;
+    else
+      if (bits_per_pixel < 16)
+        (void) TransformImageColorspace(image,image->colorspace,exception);
     if (bits_per_pixel < 8)
       {
         (void) TransformImageColorspace(image,GRAYColorspace,exception);
@@ -798,7 +817,7 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
       {
         if (flags & PALM_HAS_COLORMAP_FLAG)  /* Write out colormap */
           {
-            quantize_info->dither_method=IsPaletteImage(image,exception)
+            quantize_info->dither_method=IdentifyPaletteImage(image,exception)
               == MagickFalse ? RiemersmaDitherMethod : NoDitherMethod;
             quantize_info->number_colors=image->colors;
             (void) QuantizeImage(quantize_info,image,exception);
@@ -828,6 +847,8 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
           for (y=0; y < (ssize_t) image->rows; y++)
           {
             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+            if (q == (Quantum *) NULL)
+              break;
             for (x=0; x < (ssize_t) image->columns; x++)
             {
               SetPixelIndex(image,(Quantum) FindColor(&image->colormap[(ssize_t)
@@ -840,15 +861,24 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
       }
     if (flags & PALM_IS_COMPRESSED_FLAG)
       (void) WriteBlobMSBShort(image,0);  /* fill in size later */
-    lastrow=(unsigned char *) NULL;
+    last_row=(unsigned char *) NULL;
     if (image_info->compression == FaxCompression)
-      lastrow=(unsigned char *) AcquireQuantumMemory(bytes_per_row,
-        sizeof(*lastrow));
-      /* TODO check whether memory really was acquired? */
+      {
+        last_row=(unsigned char *) AcquireQuantumMemory(bytes_per_row,
+          sizeof(*last_row));
+        if (last_row == (unsigned char *) NULL)
+          {
+            quantize_info=DestroyQuantizeInfo(quantize_info);
+            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+          }
+      }
     one_row=(unsigned char *) AcquireQuantumMemory(bytes_per_row,
       sizeof(*one_row));
     if (one_row == (unsigned char *) NULL)
-      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+      {
+        quantize_info=DestroyQuantizeInfo(quantize_info);
+        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+      }
     for (y=0; y < (ssize_t) image->rows; y++)
     {
       ptr=one_row;
@@ -928,7 +958,7 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
               tptr = tmpbuf;
               for (bit=0, byte=0; bit < (unsigned char) MagickMin(8,(ssize_t) bytes_per_row-x); bit++)
               {
-                if ((y == 0) || (lastrow[x + bit] != one_row[x + bit]))
+                if ((y == 0) || (last_row[x + bit] != one_row[x + bit]))
                   {
                     byte |= (1 << (7 - bit));
                     *tptr++ = (char) one_row[x + bit];
@@ -937,7 +967,7 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
               (void) WriteBlobByte(image, byte);
               (void) WriteBlob(image,tptr-tmpbuf,(unsigned char *) tmpbuf);
             }
-            (void) CopyMagickMemory(lastrow,one_row,bytes_per_row);
+            (void) CopyMagickMemory(last_row,one_row,bytes_per_row);
           }
         else
           (void) WriteBlob(image,bytes_per_row,one_row);
@@ -953,9 +983,12 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
       {
         offset=SeekBlob(image,currentOffset+20,SEEK_SET);
         (void) WriteBlobByte(image,0);  /* reserved by Palm */
-        (void) WriteBlobByte(image,(unsigned char) ((31*transpix.red)/QuantumRange));
-        (void) WriteBlobByte(image,(unsigned char) ((63*transpix.green)/QuantumRange));
-        (void) WriteBlobByte(image,(unsigned char) ((31*transpix.blue)/QuantumRange));
+        (void) WriteBlobByte(image,(unsigned char) ((31*transpix.red)/
+          QuantumRange));
+        (void) WriteBlobByte(image,(unsigned char) ((63*transpix.green)/
+          QuantumRange));
+        (void) WriteBlobByte(image,(unsigned char) ((31*transpix.blue)/
+          QuantumRange));
       }
     if (flags & PALM_IS_COMPRESSED_FLAG)  /* fill in size now */
       {
@@ -965,15 +998,13 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
       }
     if (one_row != (unsigned char *) NULL) 
       one_row=(unsigned char *) RelinquishMagickMemory(one_row);
-    if (lastrow != (unsigned char *) NULL) 
-      lastrow=(unsigned char *) RelinquishMagickMemory(lastrow);
+    if (last_row != (unsigned char *) NULL) 
+      last_row=(unsigned char *) RelinquishMagickMemory(last_row);
     if (GetNextImageInList(image) == (Image *) NULL)
       break;
     /* padding to 4 byte word */
-    for (cc = (GetBlobSize(image))%4; cc > 0; cc--)
-    {
+    for (cc=(GetBlobSize(image)) % 4; cc > 0; cc--)
       (void) WriteBlobByte(image,0);
-    } 
     /* write nextDepthOffset and return to end of image */
     offset=SeekBlob(image,currentOffset+10,SEEK_SET);
     nextDepthOffset=(size_t) ((GetBlobSize(image)-currentOffset)/4);