File GraphicsMagick-CVE-2017-17912.patch of Package GraphicsMagick.7782

diff -r 7076768d4c71 -r 0d871e813a4f coders/tiff.c
--- a/coders/tiff.c	Sun Dec 17 13:00:25 2017 -0600
+++ b/coders/tiff.c	Fri Dec 22 14:38:42 2017 -0600
@@ -682,53 +682,122 @@
   return result;
 }
 
+/*
+  Locate and store Photoshop or IPTC profiles.
+
+  Arguments:
+
+  text - Pointer to octet buffer
+  length - Number of bytes or 32-bit words in buffer
+  image  - Image to store into
+  type   - TIFF tag (TIFFTAG_PHOTOSHOP or TIFFTAG_RICHTIFFIPTC)
+
+  If the tag is TIFFTAG_RICHTIFFIPTC then it appears that the length
+  represents the number of 32-bit words.  If the tag is
+  TIFFTAG_PHOTOSHOP then the length is in bytes, but the underlying
+  data is stored in units of 16-bit words.
+ */
+#define NEWSP_REMAINING(base_p,current_p,length) ((ssize_t) length-(current_p-base_p))
 static unsigned int
-ReadNewsProfile(char *text,long int length,Image *image,int type)
+ReadNewsProfile(const unsigned char *text,const size_t length,Image *image,const int type)
 {
-  register unsigned char
+  register const unsigned char
     *p;
 
-  if (length <= 0)
-    return(False);
+#if defined(GET_ONLY_IPTC_DATA)
+  static const char tag_header [] = "8BIM44";
+#else
+  static const char tag_header [] = "8BIM";
+#endif
+
+  MagickBool found_header=MagickFalse;
+
+  if ((length == 0) || ((ssize_t) length < 0))
+    return MagickFail;
+
   p=(unsigned char *) text;
   if (type == TIFFTAG_RICHTIFFIPTC)
     {
       /*
-        Handle IPTC tag.
+        Handle IPTC tag (length is number of 32-bit words).
       */
-      length*=4;
-      return SetImageProfile(image,"IPTC",p,(size_t) length);
+      return SetImageProfile(image,"IPTC",p,(size_t) length*4U);
     }
   /*
-    Handle PHOTOSHOP tag.
+    Handle PHOTOSHOP tag (length is in bytes, but data is organized as
+    array of 16-bit values.
   */
-  while (length > 0)
-  {
-#if defined(GET_ONLY_IPTC_DATA)
-    if (LocaleNCompare((char *) p,"8BIM44",6) == 0)
-#else
-    if (LocaleNCompare((char *) p,"8BIM",4) == 0)
-#endif
-      break;
-    length-=2;
-    p+=2;
-  }
-  if (length <= 0)
-    return(False);
+  while (NEWSP_REMAINING(text,p,length) > (ssize_t) sizeof(tag_header))
+    {
+      if (LocaleNCompare((char *) p,tag_header,sizeof(tag_header)-1) == 0)
+        {
+          found_header=MagickTrue;
+          break;
+        }
+      p+=2;
+    }
+  if (!found_header)
+    {
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "Failed to find %s header, ignoring profile.",
+                            tag_header);
+      return MagickFail;
+    }
 #if defined(GET_ONLY_IPTC_DATA)
   /*
     Eat OSType, IPTC ID code, and Pascal string length bytes.
   */
-  p+=6;
-  length=(*p++);
-  if (length)
-    p+=length;
-  if ((length & 0x01) == 0)
-    p++;  /* align to an even byte boundary */
-  length=(p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
-  p+=4;
+  do
+    {
+      magick_uint32_t
+        hdr_length;
+
+      p+=sizeof(tag_header)-1;
+      if (NEWSP_REMAINING(text,p,length) < 8)
+        {
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "Truncated profile: %" MAGICK_SIZE_T_F
+                                "u bytes, %" MAGICK_SSIZE_T_F "u remaining"
+                                ", ignoring profile.",
+                                (MAGICK_SIZE_T) length,
+                                (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length));
+          break;
+        }
+      hdr_length=(*p++);
+      p+=hdr_length;
+      if (NEWSP_REMAINING(text,p,length) < 8)
+        {
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "Truncated profile: %" MAGICK_SIZE_T_F
+                                "u bytes, %" MAGICK_SSIZE_T_F "u remaining"
+                                ", ignoring profile.",
+                                (MAGICK_SIZE_T) length,
+                                (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length));
+          break;
+        }
+      if ((hdr_length & 0x01) == 0)
+        p++;  /* align to an even byte boundary */
+      hdr_length=(p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+      p+=4;
+      if (((ssize_t) hdr_length <= 0) ||
+          ((ssize_t) hdr_length > NEWSP_REMAINING(text,p,length)))
+        {
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "Truncated profile: %" MAGICK_SIZE_T_F
+                                "u bytes, %" MAGICK_SSIZE_T_F "u "
+                                "remaining (need %u more bytes)"
+                                ", ignoring profile.",
+                                (MAGICK_SIZE_T) length,
+                                (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length),
+                                hdr_length);
+          return MagickFail;
+        }
+      return SetImageProfile(image,"8BIM",p,hdr_length);
+    } while (0);
+  return MagickFail;
+#else
+  return SetImageProfile(image,"8BIM",p,(size_t) NEWSP_REMAINING(text,p,length));
 #endif
-  return SetImageProfile(image,"8BIM",p,(size_t) length);
 }
 
 /*
@@ -1903,7 +1972,7 @@
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                   "Photoshop embedded profile with length %lu bytes",
                                   (unsigned long) length);
-            (void) ReadNewsProfile(text,(long) length,image,TIFFTAG_PHOTOSHOP);
+            (void) ReadNewsProfile((unsigned char *) text,(long) length,image,TIFFTAG_PHOTOSHOP);
           }
 #elif defined(TIFFTAG_RICHTIFFIPTC)
         /* IPTC TAG from RichTIFF specifications */
@@ -1913,7 +1982,7 @@
               TIFFSwabArrayOfLong((uint32 *) text,length);
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                   "IPTC Newsphoto embedded profile with length %u bytes",length);
-            ReadNewsProfile(text,length,image,TIFFTAG_RICHTIFFIPTC);
+            ReadNewsProfile((unsigned char *) text,length,image,TIFFTAG_RICHTIFFIPTC);
           }
 #endif
         /*


openSUSE Build Service is sponsored by