]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/profile.c
Handle short months in png_write_iTIME()
[imagemagick] / MagickCore / profile.c
index 4fca905fa0980de0ea52a5df30f24f2260e82ae1..2204b162352708bd7330ff8707b38feeda0fb126 100644 (file)
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2017 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,          %
@@ -47,8 +47,8 @@
 #include "MagickCore/configure.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
-#include "MagickCore/hashmap.h"
 #include "MagickCore/image.h"
+#include "MagickCore/linked-list.h"
 #include "MagickCore/memory_.h"
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
@@ -436,8 +436,12 @@ static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
     *image;
 
   cms_exception=(CMSExceptionInfo *) context;
-  image=cms_exception->image;
+  if (cms_exception == (CMSExceptionInfo *) NULL)
+    return;
   exception=cms_exception->exception;
+  if (exception == (ExceptionInfo *) NULL)
+    return;
+  image=cms_exception->image;
   if (image == (Image *) NULL)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
@@ -883,9 +887,6 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
             int
               intent;
 
-            MagickBooleanType
-              status;
-
             MagickOffsetType
               progress;
 
@@ -1102,7 +1103,6 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               }
             if (target_colorspace == CMYKColorspace)
               (void) SetImageColorspace(image,target_colorspace,exception);
-            status=MagickTrue;
             progress=0;
             image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
@@ -1218,7 +1218,8 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
             target_pixels=DestroyPixelThreadSet(target_pixels);
             source_pixels=DestroyPixelThreadSet(source_pixels);
             transform=DestroyTransformThreadSet(transform);
-            if (cmsGetDeviceClass(source_profile) != cmsSigLinkClass)
+            if ((status != MagickFalse) &&
+                (cmsGetDeviceClass(source_profile) != cmsSigLinkClass))
               status=SetImageProfile(image,name,profile,exception);
             if (target_profile != (cmsHPROFILE) NULL)
               (void) cmsCloseProfile(target_profile);
@@ -1354,20 +1355,22 @@ static inline const unsigned char *ReadResourceByte(const unsigned char *p,
 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
   unsigned int *quantum)
 {
-  *quantum=(size_t) (*p++ << 24);
-  *quantum|=(size_t) (*p++ << 16);
-  *quantum|=(size_t) (*p++ << 8);
-  *quantum|=(size_t) (*p++ << 0);
+  *quantum=(unsigned int) (*p++) << 24;
+  *quantum|=(unsigned int) (*p++) << 16;
+  *quantum|=(unsigned int) (*p++) << 8;
+  *quantum|=(unsigned int) (*p++);
   return(p);
 }
 
 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
   unsigned short *quantum)
 {
-  *quantum=(unsigned short) (*p++ << 8);
-  *quantum|=(unsigned short) (*p++ << 0);
+  *quantum=(unsigned short) (*p++) << 8;
+  *quantum|=(unsigned short) (*p++);
   return(p);
-}static inline void WriteResourceLong(unsigned char *p,
+}
+
+static inline void WriteResourceLong(unsigned char *p,
   const unsigned int quantum)
 {
   unsigned char
@@ -1442,7 +1445,8 @@ static void WriteTo8BimProfile(Image *image,const char *name,
     count=(ssize_t) value;
     if ((count & 0x01) != 0)
       count++;
-    if ((p > (datum+length-count)) || (count > (ssize_t) length))
+    if ((count < 0) || (p > (datum+length-count)) ||
+        (count > (ssize_t) length))
       break;
     if (id != profile_id)
       p+=count;
@@ -1453,12 +1457,12 @@ static void WriteTo8BimProfile(Image *image,const char *name,
           offset;
 
         ssize_t
-          extract_count;
+          extract_extent;
 
         StringInfo
           *extract_profile;
 
-        extract_count=0;
+        extract_extent=0;
         extent=(datum+length)-(p+count);
         if (profile == (StringInfo *) NULL)
           {
@@ -1469,17 +1473,17 @@ static void WriteTo8BimProfile(Image *image,const char *name,
         else
           {
             offset=(p-datum);
-            extract_count=profile->length;
-            if ((extract_count & 0x01) != 0)
-              extract_count++;
-            extract_profile=AcquireStringInfo(offset+extract_count+extent);
+            extract_extent=profile->length;
+            if ((extract_extent & 0x01) != 0)
+              extract_extent++;
+            extract_profile=AcquireStringInfo(offset+extract_extent+extent);
             (void) CopyMagickMemory(extract_profile->datum,datum,offset-4);
-            WriteResourceLong(extract_profile->datum+offset-4,
-              (unsigned int)profile->length);
+            WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
+              profile->length);
             (void) CopyMagickMemory(extract_profile->datum+offset,
               profile->datum,profile->length);
           }
-        (void) CopyMagickMemory(extract_profile->datum+offset+extract_count,
+        (void) CopyMagickMemory(extract_profile->datum+offset+extract_extent,
           p+count,extent);
         (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
           ConstantString("8bim"),CloneStringInfo(extract_profile));
@@ -1510,8 +1514,8 @@ static void GetProfilesFromResourceBlock(Image *image,
   unsigned char
     length_byte;
 
-   unsigned int
-     value;
+  unsigned int
+    value;
 
   unsigned short
     id;
@@ -1663,8 +1667,9 @@ static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
     {
       if (LocaleCompare(name,"8bim") == 0)
         GetProfilesFromResourceBlock(image,profile,exception);
-      else if (recursive == MagickFalse)
-        WriteTo8BimProfile(image,name,profile);
+      else
+        if (recursive == MagickFalse)
+          WriteTo8BimProfile(image,name,profile);
     }
   /*
     Inject profile into image properties.
@@ -1716,42 +1721,69 @@ static inline int ReadProfileByte(unsigned char **p,size_t *length)
   return(c);
 }
 
-static inline unsigned short ReadProfileShort(const EndianType endian,
+static inline signed short ReadProfileShort(const EndianType endian,
   unsigned char *buffer)
 {
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
   unsigned short
     value;
 
   if (endian == LSBEndian)
     {
-      value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
-      return((unsigned short) (value & 0xffff));
+      value=(unsigned short) buffer[1] << 8;
+      value|=(unsigned short) buffer[0];
+      quantum.unsigned_value=value & 0xffff;
+      return(quantum.signed_value);
     }
-  value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
-    ((unsigned char *) buffer)[1]);
-  return((unsigned short) (value & 0xffff));
+  value=(unsigned short) buffer[0] << 8;
+  value|=(unsigned short) buffer[1];
+  quantum.unsigned_value=value & 0xffff;
+  return(quantum.signed_value);
 }
 
-static inline unsigned int ReadProfileLong(const EndianType endian,
+static inline signed int ReadProfileLong(const EndianType endian,
   unsigned char *buffer)
 {
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
   unsigned int
     value;
 
   if (endian == LSBEndian)
     {
-      value=(unsigned int) ((buffer[3] << 24) | (buffer[2] << 16) |
-        (buffer[1] << 8 ) | (buffer[0]));
-      return((unsigned int) (value & 0xffffffff));
+      value=(unsigned int) buffer[3] << 24;
+      value|=(unsigned int) buffer[2] << 16;
+      value|=(unsigned int) buffer[1] << 8;
+      value|=(unsigned int) buffer[0];
+      quantum.unsigned_value=value & 0xffffffff;
+      return(quantum.signed_value);
     }
-  value=(unsigned int) ((buffer[0] << 24) | (buffer[1] << 16) |
-    (buffer[2] << 8) | buffer[3]);
-  return((unsigned int) (value & 0xffffffff));
+  value=(unsigned int) buffer[0] << 24;
+  value|=(unsigned int) buffer[1] << 16;
+  value|=(unsigned int) buffer[2] << 8;
+  value|=(unsigned int) buffer[3];
+  quantum.unsigned_value=value & 0xffffffff;
+  return(quantum.signed_value);
 }
 
-static inline unsigned int ReadProfileMSBLong(unsigned char **p,size_t *length)
+static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
 {
-  unsigned int
+  signed int
     value;
 
   if (*length < 4)
@@ -1762,10 +1794,10 @@ static inline unsigned int ReadProfileMSBLong(unsigned char **p,size_t *length)
   return(value);
 }
 
-static inline unsigned short ReadProfileMSBShort(unsigned char **p,
+static inline signed short ReadProfileMSBShort(unsigned char **p,
   size_t *length)
 {
-  unsigned short
+  signed short
     value;
 
   if (*length < 2)
@@ -1857,17 +1889,17 @@ static MagickBooleanType Sync8BimProfile(Image *image,StringInfo *profile)
     if ((id == 0x3ED) && (count == 16))
       {
         if (image->units == PixelsPerCentimeterResolution)
-          WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.x*2.54*
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
             65536.0),p);
         else
-          WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.x*
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
             65536.0),p);
         WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
         if (image->units == PixelsPerCentimeterResolution)
-          WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.y*2.54*
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
             65536.0),p+8);
         else
-          WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.y*
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
             65536.0),p+8);
         WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
       }
@@ -1905,6 +1937,9 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
     length,
     number_entries;
 
+  SplayTreeInfo
+    *exif_resources;
+
   ssize_t
     id,
     level,
@@ -1960,12 +1995,14 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
   /*
     This the offset to the first IFD.
   */
-  offset=(ssize_t) ((int) ReadProfileLong(endian,exif+4));
-  if ((offset < 0) || (size_t) offset >= length)
+  offset=(ssize_t) ReadProfileLong(endian,exif+4);
+  if ((offset < 0) || ((size_t) offset >= length))
     return(MagickFalse);
   directory=exif+offset;
   level=0;
   entry=0;
+  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
+    (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
   do
   {
     if (level > 0)
@@ -1997,11 +2034,18 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
         tag_value;
 
       q=(unsigned char *) (directory+2+(12*entry));
+      if (q > (exif+length-12))
+        break;  /* corrupt EXIF */
+      if (GetValueFromSplayTree(exif_resources,q) == q)
+        break;
+      (void) AddValueToSplayTree(exif_resources,q,q);
       tag_value=(ssize_t) ReadProfileShort(endian,q);
       format=(ssize_t) ReadProfileShort(endian,q+2);
-      if ((format-1) >= EXIF_NUM_FORMATS)
+      if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
         break;
-      components=(ssize_t) ((int) ReadProfileLong(endian,q+4));
+      components=(int) ReadProfileLong(endian,q+4);
+      if (components < 0)
+        break;  /* corrupt EXIF */
       number_bytes=(size_t) components*format_bytes[format];
       if ((ssize_t) number_bytes < components)
         break;  /* prevent overflow */
@@ -2009,14 +2053,11 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
         p=q+8;
       else
         {
-          ssize_t
-            offset;
-
           /*
             The directory entry contains an offset.
           */
-          offset=(ssize_t) ((int) ReadProfileLong(endian,q+8));
-          if ((size_t) (offset+number_bytes) > length)
+          offset=(ssize_t) ReadProfileLong(endian,q+8);
+          if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
             continue;
           if (~length < number_bytes)
             continue;  /* prevent overflow */
@@ -2062,10 +2103,7 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
       }
       if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
         {
-          ssize_t
-            offset;
-
-          offset=(ssize_t) ((int) ReadProfileLong(endian,p));
+          offset=(ssize_t) ReadProfileLong(endian,p);
           if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
             {
               directory_stack[level].directory=directory;
@@ -2077,8 +2115,8 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
               level++;
               if ((directory+2+(12*number_entries)) > (exif+length))
                 break;
-              offset=(ssize_t) ((int) ReadProfileLong(endian,directory+2+(12*
-                number_entries)));
+              offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
+                number_entries));
               if ((offset != 0) && ((size_t) offset < length) &&
                   (level < (MaxDirectoryStack-2)))
                 {
@@ -2091,6 +2129,7 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
         }
     }
   } while (level > 0);
+  exif_resources=DestroySplayTree(exif_resources);
   return(MagickTrue);
 }