File GraphicsMagick-CVE-2016-7524.patch of Package GraphicsMagick.6323

ff -r 4f748e625c82 -r 8da95e3e5e81 coders/meta.c
Index: GraphicsMagick-1.3.21/coders/meta.c
===================================================================
--- GraphicsMagick-1.3.21.orig/coders/meta.c	2015-02-28 21:51:58.000000000 +0100
@@ -129,14 +129,16 @@ static unsigned int IsMETA(const unsigne
 
 typedef struct _html_code
 {
-  short
+  unsigned short
     len;
+
   const char
     *code,
     val;
+
 } html_code;
 
-static html_code html_codes[] = {
+static html_code const html_codes[] = {
 #ifdef HANDLE_GT_LT
   { 4,"&lt;",'<' },
   { 4,"&gt;",'>' },
@@ -179,29 +181,36 @@ static int stringnicmp(const char *p,con
   return(toupper((int) *p)-toupper((int) *q));
 }
 
-static int convertHTMLcodes(char *s, int len)
+static size_t convertHTMLcodes(char *s, const size_t len)
 {
-  if (len <=0 || s==(char*)NULL || *s=='\0')
+  int val;
+
+  if ((len == 0) || (s == (char*) NULL) || (*s=='\0'))
     return 0;
 
-  if (s[1] == '#')
-    {
-      int val, o;
+  /*
+    Check for hex or decimal character escape.
 
-      if (sscanf(s,"&#%d;",&val) == 1)
-      {
-        o = 3;
-        while (s[o] != ';')
+    e.g. hex: "&#xA0;", decimal "&#160;"
+
+    Note that scanf is expected to parse the number in hex or decimal
+    and that it does not require the terminating ';' to appear in
+    order to parse the numeric argument.
+  */
+  if ((len > 3) && (s[1] == '#') && (strchr(s,';') != (char *) NULL) &&
+      (sscanf(s,"&#%d;",&val) == 1))
+    {
+      size_t o = 3;
+      while (s[o] != ';')
         {
           o++;
           if (o > 5)
             break;
         }
-        if (o < 6)
-          (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
-        *s = val;
-        return o;
-      }
+      if (o < 6)
+        (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
+      *s = val;
+      return o;
     }
   else
     {
@@ -281,10 +290,10 @@ static long parse8BIM(Image *ifile, Imag
   char
     brkused,
     quoted,
-    *line,
-    *token,
-    *newstr,
-    *name;
+    *line = (char *) NULL,
+    *token = (char *) NULL,
+    *newstr = (char *) NULL,
+    *name = (char *) NULL;
 
   int
     state,
@@ -299,7 +308,7 @@ static long parse8BIM(Image *ifile, Imag
   size_t
     inputlen = BUFFER_SZ;
 
-  long
+  ssize_t
     savedolen = 0L,
     outputlen = 0L;
 
@@ -313,7 +322,8 @@ static long parse8BIM(Image *ifile, Imag
   dataset = 0;
   recnum = 0;
   line = MagickAllocateMemory(char *,inputlen);
-  name = token = (char *)NULL;
+  if (line == (char *) NULL)
+    goto parse8BIM_failure;
   savedpos = 0;
   while(super_fgets(&line,&inputlen,ifile)!=NULL)
   {
@@ -321,7 +331,11 @@ static long parse8BIM(Image *ifile, Imag
     next=0;
 
     token = MagickAllocateMemory(char *,inputlen);
+    if (token == (char *) NULL)
+      goto parse8BIM_failure;
     newstr = MagickAllocateMemory(char *,inputlen);
+    if (newstr == (char *) NULL)
+      goto parse8BIM_failure;
     while (Tokenizer(&token_info, 0, token, inputlen, line,
           (char *) "", (char *) "=",
       (char *) "\"", 0, &brkused,&next,&quoted)==0)
@@ -354,8 +368,9 @@ static long parse8BIM(Image *ifile, Imag
                 break;
               case 2:
                 name = MagickAllocateMemory(char *,strlen(newstr)+1);
-                if (name)
-                  (void) strcpy(name,newstr);
+                if (name == (char *) NULL)
+                  goto parse8BIM_failure;
+                (void) strcpy(name,newstr);
                 break;
             }
             state++;
@@ -367,7 +382,7 @@ static long parse8BIM(Image *ifile, Imag
             int
               next;
 
-            unsigned long
+            size_t
               len;
 
             char
@@ -384,7 +399,7 @@ static long parse8BIM(Image *ifile, Imag
                   char
                     *s = &token[next-1];
 
-                  len -= convertHTMLcodes(s, (int) strlen(s));
+                  len -= convertHTMLcodes(s, strlen(s));
                 }
             }
 
@@ -400,6 +415,8 @@ static long parse8BIM(Image *ifile, Imag
                   {
                     long diff = outputlen - savedolen;
                     currentpos = TellBlob(ofile);
+                    if (currentpos < 0)
+                      goto parse8BIM_failure;
                     (void) SeekBlob(ofile,savedpos,SEEK_SET);
                     (void) WriteBlobMSBLong(ofile,diff);
                     (void) SeekBlob(ofile,currentpos,SEEK_SET);
@@ -433,7 +450,7 @@ static long parse8BIM(Image *ifile, Imag
                     next=0;
                     outputlen += len;
                     while (len--)
-                      (void) WriteBlobByte(ofile,token[next++]);
+                      (void) WriteBlobByte(ofile,token[next++]); /* boom */
 
                     if (outputlen & 1)
                       {
@@ -445,6 +462,8 @@ static long parse8BIM(Image *ifile, Imag
                   {
                     /* patch in a fake length for now and fix it later */
                     savedpos = TellBlob(ofile);
+                    if (savedpos < 0)
+                      goto parse8BIM_failure;
                     (void) WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
                     outputlen += 4;
                     savedolen = outputlen;
@@ -478,12 +497,22 @@ static long parse8BIM(Image *ifile, Imag
       long diff = outputlen - savedolen;
 
       currentpos = TellBlob(ofile);
+      if (currentpos < 0)
+        goto parse8BIM_failure;
+
       (void) SeekBlob(ofile,savedpos,SEEK_SET);
       (void) WriteBlobMSBLong(ofile,diff);
       (void) SeekBlob(ofile,currentpos,SEEK_SET);
       savedolen = 0L;
     }
   return outputlen;
+
+ parse8BIM_failure:
+  MagickFreeMemory(token);
+  MagickFreeMemory(newstr);
+  MagickFreeMemory(name);
+  MagickFreeMemory(line);
+  return 0L;
 }
 
 static char *super_fgets_w(char **b, size_t *blen, Image *file)
@@ -542,10 +571,10 @@ static long parse8BIMW(Image *ifile, Ima
   char
     brkused,
     quoted,
-    *line,
-    *token,
-    *newstr,
-    *name;
+    *line = (char *) NULL,
+    *token = (char *) NULL,
+    *newstr = (char *) NULL,
+    *name = (char *) NULL;
 
   int
     state,
@@ -560,7 +589,7 @@ static long parse8BIMW(Image *ifile, Ima
   size_t
     inputlen = BUFFER_SZ;
 
-  long
+  ssize_t
     savedolen = 0L,
     outputlen = 0L;
 
@@ -574,6 +603,8 @@ static long parse8BIMW(Image *ifile, Ima
   dataset = 0;
   recnum = 0;
   line = MagickAllocateMemory(char *,inputlen);
+  if (line == (char *) NULL)
+    goto parse8BIMW_failure;
   name = token = (char *)NULL;
   savedpos = 0;
   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -586,7 +617,11 @@ static long parse8BIMW(Image *ifile, Ima
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "META CODER Parse8BIM: %s (%lu)",line, (unsigned long) inputlen);
     token = MagickAllocateMemory(char *,inputlen);
+    if (token == (char *) NULL)
+      goto parse8BIMW_failure;
     newstr = MagickAllocateMemory(char *,inputlen);
+    if (newstr == (char *) NULL)
+      goto parse8BIMW_failure;
     while (Tokenizer(&token_info, 0, token, inputlen, line,
           (char *) "", (char *) "=",
       (char *) "\"", 0, &brkused,&next,&quoted)==0)
@@ -619,8 +654,9 @@ static long parse8BIMW(Image *ifile, Ima
                 break;
               case 2:
                 name = MagickAllocateMemory(char *,strlen(newstr)+1);
-                if (name)
-                  (void) strcpy(name,newstr);
+                if (name == (char *) NULL)
+                  goto parse8BIMW_failure;
+                (void) strcpy(name,newstr);
                 break;
             }
             state++;
@@ -632,7 +668,7 @@ static long parse8BIMW(Image *ifile, Ima
             int
               next;
 
-            unsigned long
+            size_t
               len;
 
             char
@@ -649,7 +685,7 @@ static long parse8BIMW(Image *ifile, Ima
                   char
                     *s = &token[next-1];
 
-                  len -= convertHTMLcodes(s, (int) strlen(s));
+                  len -= convertHTMLcodes(s, strlen(s));
                 }
             }
 
@@ -665,6 +701,8 @@ static long parse8BIMW(Image *ifile, Ima
                   {
                     long diff = outputlen - savedolen;
                     currentpos = TellBlob(ofile);
+                    if (currentpos < 0)
+                      goto parse8BIMW_failure;
                     (void) SeekBlob(ofile,savedpos,SEEK_SET);
                     (void) WriteBlobMSBLong(ofile,diff);
                     (void) SeekBlob(ofile,currentpos,SEEK_SET);
@@ -710,6 +748,8 @@ static long parse8BIMW(Image *ifile, Ima
                   {
                     /* patch in a fake length for now and fix it later */
                     savedpos = TellBlob(ofile);
+                    if (savedpos < 0)
+                      goto parse8BIMW_failure;
                     (void) WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
                     outputlen += 4;
                     savedolen = outputlen;
@@ -743,12 +783,21 @@ static long parse8BIMW(Image *ifile, Ima
       long diff = outputlen - savedolen;
 
       currentpos = TellBlob(ofile);
+      if (currentpos < 0)
+        goto parse8BIMW_failure;
       (void) SeekBlob(ofile,savedpos,SEEK_SET);
       (void) WriteBlobMSBLong(ofile,diff);
       (void) SeekBlob(ofile,currentpos,SEEK_SET);
       savedolen = 0L;
     }
   return outputlen;
+
+ parse8BIMW_failure:
+  MagickFreeMemory(token);
+  MagickFreeMemory(newstr);
+  MagickFreeMemory(name);
+  MagickFreeMemory(line);
+  return 0L;
 }
 
 /* some defines for the different JPEG block types */
@@ -835,11 +884,12 @@ static int jpeg_skip_variable(Image *ifi
   return 0;
 }
 
-static int jpeg_skip_variable2(Image *ifile, Image *ARGUNUSED(ofile))
+static int jpeg_skip_variable2(Image *ifile, Image *ofile)
 {
   unsigned int  length;
   int c1,c2;
 
+  ARG_NOT_USED(ofile);
   if ((c1 = ReadBlobByte(ifile)) == EOF) return M_EOI;
   if ((c2 = ReadBlobByte(ifile)) == EOF) return M_EOI;
 
@@ -908,8 +958,6 @@ static int jpeg_skip_till_marker(Image *
 }
 #endif
 
-static char psheader[] = "\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0";
-
 /* Embed binary IPTC data into a JPEG image. */
 static int jpeg_embed(Image *ifile, Image *ofile, Image *iptc)
 {
@@ -952,9 +1000,12 @@ static int jpeg_embed(Image *ifile, Imag
 
         if (iptc != (Image *)NULL)
           {
+            static const char psheader_base[] = "\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0";
+            char psheader[sizeof(psheader_base)];
             len=GetBlobSize(iptc);
             if (len & 1)
               len++; /* make the length even */
+            (void) strlcpy(psheader,psheader_base,sizeof(psheader));
             psheader[ 2 ] = (len+16)>>8;
             psheader[ 3 ] = (len+16)&0xff;
             for (inx = 0; inx < 18; inx++)
@@ -1250,7 +1301,7 @@ static Image *ReadMETAImage(const ImageI
 
       DestroyImage(buff);
     }
-  if (LocaleCompare(image_info->magick,"IPTC") == 0)
+  if (LocaleNCompare(image_info->magick,"IPTC",4) == 0)
     {
       buff=AllocateImage((ImageInfo *) NULL);
       if (buff == (Image *) NULL)
@@ -1260,7 +1311,7 @@ static Image *ReadMETAImage(const ImageI
         {
           DestroyImage(buff);
           ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
-            image)
+                               image);
         }
       AttachBlob(buff->blob,blob,length);
       /* write out the header - length field patched below */
@@ -1286,14 +1337,21 @@ static Image *ReadMETAImage(const ImageI
         }
 
       /* subtract off the length of the 8BIM stuff */
+      blob=GetBlobStreamData(buff); /* blob may be realloced */
+      if ((blob == (const unsigned char *) NULL) || (GetBlobSize(buff) < 12))
+        {
+          DestroyImage(buff);
+          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
+                               image);
+        }
       length=GetBlobSize(buff)-12;
       blob[10]=(unsigned char) ((length >> 8) & 0xff);
       blob[11]=(unsigned char) (length & 0xff);
       blob=GetBlobStreamData(buff);
       length=GetBlobSize(buff);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "Store IPTC profile, size %lu bytes",
-                            (unsigned long) length);
+                            "Store IPTC profile, size %" MAGICK_SIZE_T_F
+                            "u bytes",(MAGICK_SIZE_T) length);
       (void) SetImageProfile(image,"IPTC",blob,length);
       DetachBlob(buff->blob);
       MagickFreeMemory(blob)
@@ -1840,9 +1898,14 @@ static int formatIPTC(Image *ifile, Imag
     else
       {
         if (foundiptc)
-          return -1;
+          {
+            return -1;
+          }
         else
-          continue;
+          {
+            c = ReadBlobByte(ifile);
+            continue;
+          }
       }
 
     /* we found the 0x1c tag and now grab the dataset and record number tags */
@@ -1888,7 +1951,11 @@ static int formatIPTC(Image *ifile, Imag
     for (tagindx=0; tagindx<taglen; tagindx++)
     {
       c=ReadBlobByte(ifile);
-      if (c == EOF) return -1;
+      if (c == EOF)
+        {
+          MagickFreeMemory(str);
+          return -1;
+        }
       str[tagindx] = (unsigned char) c;
     }
     str[taglen] = 0;
@@ -2011,7 +2078,11 @@ static int formatIPTCfromBuffer(Image *o
     for (tagindx=0; tagindx<taglen; tagindx++)
     {
       c = *s++; len--;
-      if (len < 0) return -1;
+      if (len < 0)
+        {
+          MagickFreeMemory(str);
+          return -1;
+        }
       str[tagindx] = (unsigned char) c;
     }
     str[ taglen ] = 0;
@@ -2030,6 +2101,13 @@ static int formatIPTCfromBuffer(Image *o
   return tagsfound;
 }
 
+#define Format8BIMLiberate()                    \
+  do                                            \
+    {                                           \
+      MagickFreeMemory(PString);                \
+      MagickFreeMemory(str);                    \
+    } while(0);
+
 static int format8BIM(Image *ifile, Image *ofile)
 {
   char
@@ -2045,109 +2123,138 @@ static int format8BIM(Image *ifile, Imag
     c;
 
   unsigned char
-    *PString,
-    *str;
+    *PString=0,
+    *str=0;
 
   resCount = 0;
 
   c =ReadBlobByte(ifile);
   while (c != EOF)
-  {
-    if (c == '8')
-      {
-        unsigned char
-          buffer[5];
+    {
+      if (c == '8')
+        {
+          unsigned char
+            buffer[5];
 
-        buffer[0] = (unsigned char) c;
-        for (i=1; i<4; i++)
+          buffer[0] = (unsigned char) c;
+          for (i=1; i<4; i++)
+            {
+              c=ReadBlobByte(ifile);
+              if (c == EOF)
+                {
+                  Format8BIMLiberate();
+                  return -1;
+                }
+              buffer[i] = (unsigned char) c;
+            }
+          buffer[4] = 0;
+          if (strcmp((const char *)buffer, "8BIM") != 0)
+            continue;
+        }
+      else
         {
           c=ReadBlobByte(ifile);
-          if (c == EOF) return -1;
-          buffer[i] = (unsigned char) c;
-        }
-        buffer[4] = 0;
-        if (strcmp((const char *)buffer, "8BIM") != 0)
           continue;
-      }
-    else
-      {
-        c=ReadBlobByte(ifile);
-        continue;
-      }
-
-    /* we found the OSType (8BIM) and now grab the ID, PString, and Size fields */
-    ID = ReadBlobMSBShort(ifile);
-    if (ID < 0) return -1;
-    {
-      unsigned char
-        plen;
+        }
 
-      c=ReadBlobByte(ifile);
-      if (c == EOF) return -1;
-      plen = (unsigned char) c;
-      PString=MagickAllocateMemory(unsigned char *,(unsigned int) (plen+1));
-      if (PString == (unsigned char *) NULL)
-      {
-        (void) printf("MemoryAllocationFailed");
-        return 0;
-      }
-      for (i=0; i<plen; i++)
-      {
-        c=ReadBlobByte(ifile);
-        if (c == EOF) return -1;
-        PString[i] = (unsigned char) c;
-      }
-      PString[ plen ] = 0;
-      if (!(plen&1))
-      {
-        c=ReadBlobByte(ifile);
-        if (c == EOF) return -1;
-      }
-    }
-    Size = ReadBlobMSBLong(ifile);
-    if (Size < 0) return -1;
-    /* make a buffer to hold the data and snag it from the input stream */
-    str=MagickAllocateMemory(unsigned char *,(size_t) Size);
-    if (str == (unsigned char *) NULL)
+      /* we found the OSType (8BIM) and now grab the ID, PString, and Size fields */
+      ID = ReadBlobMSBShort(ifile);
+      if (ID < 0)
+        {
+          Format8BIMLiberate();
+          return -1;
+        }
       {
-        (void) printf("MemoryAllocationFailed");
-        return 0;
-      }
-    for (i=0; i<Size; i++)
-    {
-      c=ReadBlobByte(ifile);
-      if (c == EOF) return -1;
-      str[i] = (unsigned char) c;
-    }
+        unsigned char
+          plen;
 
-    /* we currently skip thumbnails, since it does not make
-     * any sense preserving them in a real world application
-     */
-    if (ID != THUMBNAIL_ID)
-      {
-        /* now finish up by formatting this binary data into
-         * ASCII equivalent
-         */
-        if (strlen((const char *) PString) != 0)
-          FormatString(temp, "8BIM#%d#%s=", ID, PString);
-        else
-          FormatString(temp, "8BIM#%d=", ID);
-        (void) WriteBlobString(ofile,temp);
-        if (ID == IPTC_ID)
+        c=ReadBlobByte(ifile);
+        if (c == EOF)
           {
-            formatString(ofile, "IPTC", 4);
-            (void) formatIPTCfromBuffer(ofile, (char *)str, (long) Size);
+            Format8BIMLiberate();
+            return -1;
+          }
+        plen = (unsigned char) c;
+        PString=MagickAllocateMemory(unsigned char *,(unsigned int) (plen+1));
+        if (PString == (unsigned char *) NULL)
+          {
+            (void) printf("MemoryAllocationFailed");
+            Format8BIMLiberate();
+            return 0;
+          }
+        for (i=0; i<plen; i++)
+          {
+            c=ReadBlobByte(ifile);
+            if (c == EOF)
+              {
+                Format8BIMLiberate();
+                return -1;
+              }
+            PString[i] = (unsigned char) c;
+          }
+        PString[ plen ] = 0;
+        if (!(plen&1))
+          {
+            c=ReadBlobByte(ifile);
+            if (c == EOF)
+              {
+                Format8BIMLiberate();
+                return -1;
+              }
           }
-        else
-          formatString(ofile, (char *)str, (long) Size);
       }
-    MagickFreeMemory(str);
-    MagickFreeMemory(PString);
+      Size = ReadBlobMSBLong(ifile);
+      if (Size < 0)
+        {
+          Format8BIMLiberate();
+          return -1;
+        }
+      /* make a buffer to hold the data and snag it from the input stream */
+      str=MagickAllocateMemory(unsigned char *,(size_t) Size);
+      if (str == (unsigned char *) NULL)
+        {
+          (void) printf("MemoryAllocationFailed");
+          Format8BIMLiberate();
+          return 0;
+        }
+      for (i=0; i<Size; i++)
+        {
+          c=ReadBlobByte(ifile);
+          if (c == EOF)
+            {
+              Format8BIMLiberate();
+              return -1;
+            }
+          str[i] = (unsigned char) c;
+        }
+
+      /* we currently skip thumbnails, since it does not make
+       * any sense preserving them in a real world application
+       */
+      if (ID != THUMBNAIL_ID)
+        {
+          /* now finish up by formatting this binary data into
+           * ASCII equivalent
+           */
+          if (strlen((const char *) PString) != 0)
+            FormatString(temp, "8BIM#%d#%s=", ID, PString);
+          else
+            FormatString(temp, "8BIM#%d=", ID);
+          (void) WriteBlobString(ofile,temp);
+          if (ID == IPTC_ID)
+            {
+              formatString(ofile, "IPTC", 4);
+              (void) formatIPTCfromBuffer(ofile, (char *)str, (long) Size);
+            }
+          else
+            formatString(ofile, (char *)str, (long) Size);
+        }
+      Format8BIMLiberate();
 
-    resCount++;
+      resCount++;
 
-    c=ReadBlobByte(ifile);
-  }
+      c=ReadBlobByte(ifile);
+    }
   return resCount;
 }
 
openSUSE Build Service is sponsored by