]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/profile.c
Handle short months in png_write_iTIME()
[imagemagick] / MagickCore / profile.c
index d332da9e911f5c53d1bc12bc599e3cd4f85e837c..2204b162352708bd7330ff8707b38feeda0fb126 100644 (file)
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2015 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"
 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
 #include <wchar.h>
 #include <lcms/lcms2.h>
-#elif defined(MAGICKCORE_HAVE_LCMS2_H)
+#else
 #include <wchar.h>
 #include "lcms2.h"
-#elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
-#include <lcms/lcms.h>
-#else
-#include "lcms.h"
 #endif
 #endif
 \f
-/*
-  Define declarations.
-*/
-#if !defined(LCMS_VERSION) || (LCMS_VERSION < 2000)
-#define cmsSigCmykData icSigCmykData
-#define cmsSigGrayData icSigGrayData
-#define cmsSigLabData icSigLabData
-#define cmsSigLuvData icSigLuvData
-#define cmsSigRgbData icSigRgbData
-#define cmsSigXYZData icSigXYZData
-#define cmsSigYCbCrData icSigYCbCrData
-#define cmsSigLinkClass icSigLinkClass
-#define cmsColorSpaceSignature icColorSpaceSignature
-#define cmsUInt32Number  DWORD
-#define cmsSetLogErrorHandler(handler)  cmsSetErrorHandler(handler)
-#define cmsCreateTransformTHR(context,source_profile,source_type, \
-  target_profile,target_type,intent,flags)  cmsCreateTransform(source_profile, \
-  source_type,target_profile,target_type,intent,flags);
-#define cmsOpenProfileFromMemTHR(context,profile,length) \
-  cmsOpenProfileFromMem(profile,length)
-#endif
-
 /*
   Forward declarations
 */
@@ -363,7 +337,6 @@ MagickExport char *GetNextImageProfile(const Image *image)
 */
 
 #if defined(MAGICKCORE_LCMS_DELEGATE)
-
 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
 {
   register ssize_t
@@ -450,7 +423,6 @@ static cmsHTRANSFORM *AcquireTransformThreadSet(Image *image,
 #endif
 
 #if defined(MAGICKCORE_LCMS_DELEGATE)
-#if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
 static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
   const char *message)
 {
@@ -464,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,
@@ -478,14 +454,6 @@ static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
   (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
     "UnableToTransformColorspace","`%s'",image->filename);
 }
-#else
-static int CMSExceptionHandler(int severity,const char *message)
-{
-  (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
-    severity,message != (char *) NULL ? message : "no message");
-  return(1);
-}
-#endif
 #endif
 
 static MagickBooleanType SetsRGBImageProfile(Image *image,
@@ -909,7 +877,7 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               target_profile;
 
             cmsHTRANSFORM
-              *restrict transform;
+              *magick_restrict transform;
 
             cmsUInt32Number
               flags,
@@ -919,9 +887,6 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
             int
               intent;
 
-            MagickBooleanType
-              status;
-
             MagickOffsetType
               progress;
 
@@ -933,8 +898,8 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               y;
 
             unsigned short
-              **restrict source_pixels,
-              **restrict target_pixels;
+              **magick_restrict source_pixels,
+              **magick_restrict target_pixels;
 
             target_profile=(cmsHPROFILE) NULL;
             if (icc_profile != (StringInfo *) NULL)
@@ -1138,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)
@@ -1157,7 +1121,7 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
                 x;
 
               register Quantum
-                *restrict q;
+                *magick_restrict q;
 
               register unsigned short
                 *p;
@@ -1254,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);
@@ -1390,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
@@ -1478,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;
@@ -1489,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)
           {
@@ -1505,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));
@@ -1546,8 +1514,8 @@ static void GetProfilesFromResourceBlock(Image *image,
   unsigned char
     length_byte;
 
-   unsigned int
-     value;
+  unsigned int
+    value;
 
   unsigned short
     id;
@@ -1568,7 +1536,8 @@ static void GetProfilesFromResourceBlock(Image *image,
       break;
     p=ReadResourceLong(p,&value);
     count=(ssize_t) value;
-    if ((p > (datum+length-count)) || (count > (ssize_t) length))
+    if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
+        (count < 0))
       break;
     switch (id)
     {
@@ -1698,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.
@@ -1751,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)
@@ -1797,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)
@@ -1881,28 +1878,28 @@ static MagickBooleanType Sync8BimProfile(Image *image,StringInfo *profile)
       return(MagickFalse);
     id=ReadProfileMSBShort(&p,&length);
     count=(ssize_t) ReadProfileByte(&p,&length);
-    if (count > (ssize_t) length)
+    if ((count > (ssize_t) length) || (count < 0))
       return(MagickFalse);
     p+=count;
     if ((*p & 0x01) == 0)
       (void) ReadProfileByte(&p,&length);
     count=(ssize_t) ReadProfileMSBLong(&p,&length);
-    if (count > (ssize_t) length)
+    if ((count > (ssize_t) length) || (count < 0))
       return(MagickFalse);
     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);
       }
@@ -1940,6 +1937,9 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
     length,
     number_entries;
 
+  SplayTreeInfo
+    *exif_resources;
+
   ssize_t
     id,
     level,
@@ -1995,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)
@@ -2032,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 */
@@ -2044,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 */
@@ -2097,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;
@@ -2112,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)))
                 {
@@ -2126,6 +2129,7 @@ MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
         }
     }
   } while (level > 0);
+  exif_resources=DestroySplayTree(exif_resources);
   return(MagickTrue);
 }