ff -r 4f748e625c82 -r 8da95e3e5e81 coders/meta.c
Index: GraphicsMagick-1.2.5/coders/meta.c
===================================================================
--- GraphicsMagick-1.2.5.orig/coders/meta.c	2008-06-11 02:06:41.000000000 +0200
+++ GraphicsMagick-1.2.5/coders/meta.c	2016-10-06 15:42:56.617389326 +0200
@@ -1,5 +1,5 @@
 /*
-% Copyright (C) 2003, 2004 GraphicsMagick Group
+% Copyright (C) 2003 - 2009 GraphicsMagick Group
 % Copyright (C) 2002 ImageMagick Studio
 %
 % This program is covered by multiple licenses, which are described in
@@ -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;",'>' },
@@ -176,32 +178,39 @@ static int stringnicmp(const char *p,con
     p++;
     q++;
   }
-  return(toupper(*p)-toupper(*q));
+  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) strcpy(s+1, s+1+o);
-        *s = val;
-        return o;
-      }
+      if (o < 6)
+        (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
+      *s = val;
+      return o;
     }
   else
     {
@@ -214,7 +223,7 @@ static int convertHTMLcodes(char *s, int
         if (html_codes[i].len <= len)
           if (stringnicmp(s, html_codes[i].code, (size_t) (html_codes[i].len)) == 0)
             {
-              (void) strcpy(s+1, s+html_codes[i].len);
+              (void) memmove(s+1, s+html_codes[i].len, strlen(s+html_codes[i].len)+1);
               *s = html_codes[i].val;
               return html_codes[i].len-1;
             }
@@ -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
@@ -375,7 +390,7 @@ static long parse8BIM(Image *ifile, Imag
               quoted;
 
             next=0;
-            len = strlen(token);
+            len = (unsigned long) strlen(token);
             while (Tokenizer(&token_info,0, newstr, inputlen, token, (char *) "",
               (char *) "&", (char *) "", 0, &brkused, &next, &quoted)==0)
             {
@@ -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);
@@ -414,7 +431,7 @@ static long parse8BIM(Image *ifile, Imag
                 (void) WriteBlobMSBShort(ofile,recnum);
                 outputlen += 6;
                 if (name)
-                  nlen = strlen(name);
+                  nlen = (unsigned char) strlen(name);
                 (void) WriteBlobByte(ofile,nlen);
                 outputlen++;
                 for (i=0; i<nlen; i++)
@@ -427,13 +444,13 @@ static long parse8BIM(Image *ifile, Imag
                   }
                 if (recnum != IPTC_ID)
                   {
-                    (void) WriteBlobMSBLong(ofile, len);
+                    (void) WriteBlobMSBLong(ofile, (const magick_uint32_t) len);
                     outputlen += 4;
 
                     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;
@@ -457,7 +476,7 @@ static long parse8BIM(Image *ifile, Imag
                     (void) WriteBlobByte(ofile,0x1c);
                     (void) WriteBlobByte(ofile,dataset);
                     (void) WriteBlobByte(ofile,recnum & 255);
-                    (void) WriteBlobMSBShort(ofile,len);
+                    (void) WriteBlobMSBShort(ofile,(const magick_uint16_t) len);
                     outputlen += 5;
                     next=0;
                     outputlen += len;
@@ -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
@@ -640,7 +676,7 @@ static long parse8BIMW(Image *ifile, Ima
               quoted;
 
             next=0;
-            len = strlen(token);
+            len = (unsigned long) strlen(token);
             while (Tokenizer(&token_info,0, newstr, inputlen, token, (char *) "",
               (char *) "&", (char *) "", 0, &brkused, &next, &quoted)==0)
             {
@@ -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);
@@ -679,7 +717,7 @@ static long parse8BIMW(Image *ifile, Ima
                 (void) WriteBlobMSBShort(ofile,recnum);
                 outputlen += 6;
                 if (name)
-                  nlen = strlen(name);
+                  nlen = (unsigned char) strlen(name);
                 (void) WriteBlobByte(ofile,nlen);
                 outputlen++;
                 for (i=0; i<nlen; i++)
@@ -692,7 +730,7 @@ static long parse8BIMW(Image *ifile, Ima
                   }
                 if (recnum != IPTC_ID)
                   {
-                    (void) WriteBlobMSBLong(ofile, len);
+                    (void) WriteBlobMSBLong(ofile, (const magick_uint32_t) len);
                     outputlen += 4;
 
                     next=0;
@@ -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;
@@ -722,10 +762,10 @@ static long parse8BIMW(Image *ifile, Ima
                     (void) WriteBlobByte(ofile,0x1c);
                     (void) WriteBlobByte(ofile,dataset);
                     (void) WriteBlobByte(ofile,recnum & 255);
-                    (void) WriteBlobMSBShort(ofile,len);
+                    (void) WriteBlobMSBShort(ofile,(const magick_uint16_t) len);
                     outputlen += 5;
                     next=0;
-                    outputlen += len;
+                    outputlen += (long) len;
                     while (len--)
                       (void) WriteBlobByte(ofile,token[next++]);
                   }
@@ -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++)
@@ -1094,14 +1145,14 @@ static Image *ReadMETAImage(const ImageI
             (void) WriteBlobByte(buff,c);
           }
         }
-
+      blob=GetBlobStreamData(buff);
+      length=GetBlobSize(buff);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "Store IPTC profile, size %lu bytes",
-                            (unsigned long) GetBlobSize(buff));
-      (void) SetImageProfile(image,"IPTC",GetBlobStreamData(buff),
-                             GetBlobSize(buff));
-      /* MagickFreeMemory(blob); */
+                            (unsigned long) length);
+      (void) SetImageProfile(image,"IPTC",blob,length);
       DetachBlob(buff->blob);
+      MagickFreeMemory(blob);
       DestroyImage(buff);
     }
   if (LocaleNCompare(image_info->magick,"APP1",4) == 0)
@@ -1151,9 +1202,9 @@ static Image *ReadMETAImage(const ImageI
             }
           AttachBlob(iptc->blob,pinfo->info,pinfo->length);
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                "META CODER APP1JPEG embed: 0x%08lx (%ld)",
-                                (unsigned long) pinfo->info,
-                                (long) pinfo->length);
+                                "META CODER APP1JPEG embed: %p (%ld)",
+                                pinfo->info, /* unsigned char * */
+                                (long) pinfo->length); /* size_t */
           result=jpeg_embed(image,buff,iptc);
           DetachBlob(iptc->blob);
           DestroyImage(iptc);
@@ -1208,13 +1259,14 @@ static Image *ReadMETAImage(const ImageI
             }
 #endif
         }
+      blob=GetBlobStreamData(buff);
+      length=GetBlobSize(buff);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "Store APP1 profile, size %lu bytes",
-                            (unsigned long) GetBlobSize(buff));
-      (void) SetImageProfile(image,"APP1",GetBlobStreamData(buff),
-                             GetBlobSize(buff));
-      /* MagickFreeMemory(blob); */
+                            (unsigned long) length);
+      (void) SetImageProfile(image,"APP1",blob,length);
       DetachBlob(buff->blob);
+      MagickFreeMemory(blob);
       DestroyImage(buff);
     }
   if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
@@ -1238,17 +1290,18 @@ static Image *ReadMETAImage(const ImageI
           break;
         (void) WriteBlobByte(buff,c);
       }
+      blob=GetBlobStreamData(buff);
+      length=GetBlobSize(buff);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                             "Store ICM profile, size %lu bytes",
-                            (unsigned long) GetBlobSize(buff));
-      (void) SetImageProfile(image,"ICM",GetBlobStreamData(buff),
-                             GetBlobSize(buff));
-      /* MagickFreeMemory(blob); */
+                            (unsigned long) length);
+      (void) SetImageProfile(image,"ICM",blob,length);
       DetachBlob(buff->blob);
+      MagickFreeMemory(blob);
 
       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)
@@ -1258,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 */
@@ -1284,17 +1337,24 @@ 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]=length >> 8;
-      blob[11]=length & 0xff;
-
+      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) GetBlobSize(buff));
-      (void) SetImageProfile(image,"IPTC",GetBlobStreamData(buff),
-                             GetBlobSize(buff));
-      /* MagickFreeMemory(blob) */
+                            (unsigned long) length);
+      (void) SetImageProfile(image,"IPTC",blob,length);
       DetachBlob(buff->blob);
+      MagickFreeMemory(blob)
       DestroyImage(buff);
     }
   CloseBlob(image);
@@ -1508,9 +1568,9 @@ ModuleExport void UnregisterMETAImage(vo
 %
 */
 
-static long GetIPTCStream(const unsigned char *blob, size_t blob_length, size_t *offset)
+static size_t GetIPTCStream(const unsigned char *blob, size_t blob_length, size_t *offset)
 {
-  long
+  size_t
     info_length;
 
   register long
@@ -1520,18 +1580,71 @@ static long GetIPTCStream(const unsigned
     *p;
 
   unsigned char
-    buffer[4],
     c;
 
   unsigned int
     marker;
 
-  unsigned long
-    tag_length;
+  size_t
+    tag_length,
+    blob_remaining;
+    
+  p=blob;
+  blob_remaining=blob_length;
+  if ((*p == 0x1c) && (*(p+1) == 0x02))
+    {
+      /* This looks like a plain IPTC record 2 block so drop through */
+      *offset=0;
+      return blob_length;
+    }
+
+  /* Scan in case we are in an 8BIM block */
+  while (blob_remaining >= 12)
+  {
+    /* Check for 8BIM string ID */
+    if (strncmp((const char*)p,"8BIM",4)) break;
+    p+=4;
+    blob_remaining -= 4;
+
+    /* Read marker ID */
+    marker=(unsigned int)(*p) << 8 | *(p+1);
+    p+=2;
+    blob_remaining-=2;
+
+    /* Read length of Pascal style description string */
+    c=*p++;
+    blob_remaining--;
+    /* ...allow for possible padding byte */
+    c |= 1;
+    /* ...and skip the string data */
+    if (c >= blob_remaining) break;
+    p+=c;
+    blob_remaining-=c;
+      
+    /* Read data length */
+    if (blob_remaining < 4) break;
+    tag_length=(((unsigned long)*p) << 24) | (((unsigned long)*(p+1)) << 16) |
+               (((unsigned long)*(p+2)) << 8) | ((unsigned long)*(p+3));
+    p+=4;
+    blob_remaining-=4;
+    if (tag_length > blob_remaining) break;
+    /* Check whether we have the IPTC tag data */
+    if (marker == IPTC_ID)
+      {
+        /* All looks good so return IPTC block "as is" */
+        *offset=(unsigned long)(p-blob);
+        return tag_length;
+      }
 
-  /*
-    Find the beginning of the IPTC info.
-  */
+    /* Allow for padding of data to even size */
+    if (tag_length & 1) tag_length++;
+
+    /* Skip unwanted data */
+    p+=tag_length;
+    blob_remaining-=tag_length;
+  }
+  
+  /* Find the beginning of the IPTC info */
   p=blob;
   tag_length=0;
 iptc_find:
@@ -1594,19 +1707,21 @@ iptc_find:
     info_length++;
     if (c & (unsigned char) 0x80)
       {
-        for (i=0; i < 4; i++)
+	/* long format */
+	tag_length=0;
+	for (i=0; i < 4; i++)
         {
-          buffer[i]=(*p++);
+	  tag_length <<= 8;
+          tag_length |= (*p++);
           blob_length--;
           if (blob_length == 0)
             break;
           info_length++;
         }
-        tag_length=(((long) buffer[0]) << 24) | (((long) buffer[1]) << 16) |
-          (((long) buffer[2]) << 8) | (((long) buffer[3]));
       }
     else
       {
+	/* short format */
         tag_length=((long) c) << 8;
         c=(*p++);
         blob_length--;
@@ -1771,9 +1886,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 */
@@ -1819,7 +1939,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;
@@ -1942,7 +2066,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;
@@ -1961,6 +2089,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
@@ -1976,109 +2111,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;
 }
 
