]> granicus.if.org Git - imagemagick/blobdiff - coders/meta.c
...
[imagemagick] / coders / meta.c
index cc4341da70b191a2c361819d3be77004b739d89c..7ed42ea1f0e61a6f5660c2251956113c87cf968f 100644 (file)
 %                                 July 2001                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2018 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,          %
 /*
   Include declarations.
 */
-#include "magick/studio.h"
-#include "magick/blob.h"
-#include "magick/blob-private.h"
-#include "magick/exception.h"
-#include "magick/exception-private.h"
-#include "magick/image.h"
-#include "magick/image-private.h"
-#include "magick/list.h"
-#include "magick/magick.h"
-#include "magick/memory_.h"
-#include "magick/module.h"
-#include "magick/profile.h"
-#include "magick/splay-tree.h"
-#include "magick/quantum-private.h"
-#include "magick/static.h"
-#include "magick/string_.h"
-#include "magick/string-private.h"
-#include "magick/token.h"
-#include "magick/utility.h"
+#include "MagickCore/studio.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/channel.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/module.h"
+#include "MagickCore/profile.h"
+#include "MagickCore/splay-tree.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
+#include "MagickCore/token.h"
+#include "MagickCore/utility.h"
 \f
 /*
   Forward declarations.
 */
 static MagickBooleanType
-  WriteMETAImage(const ImageInfo *,Image *);
+  WriteMETAImage(const ImageInfo *,Image *,ExceptionInfo *);
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -139,18 +140,18 @@ static MagickBooleanType IsMETA(const unsigned char *magick,const size_t length)
 %    o exception: return any errors or warnings in this structure.
 %
 */
-#define BUFFER_SZ 4096
 
 typedef struct _html_code
 {
-  short
+  const short int
     len;
+
   const char
     *code,
     val;
 } html_code;
 
-static html_code html_codes[] = {
+static const html_code html_codes[] = {
 #ifdef HANDLE_GT_LT
   { 4,"&lt;",'<' },
   { 4,"&gt;",'>' },
@@ -193,48 +194,61 @@ static int stringnicmp(const char *p,const char *q,size_t n)
   return(toupper((int) *p)-toupper((int) *q));
 }
 
-static int convertHTMLcodes(char *s, int len)
+static size_t convertHTMLcodes(char *s)
 {
-  if (len <=0 || s==(char*)NULL || *s=='\0')
-    return 0;
+  int
+    value;
 
-  if (s[1] == '#')
-    {
-      int val, o;
+  register size_t
+    i;
+
+  size_t
+    length;
 
-      if (sscanf(s,"&#%d;",&val) == 1)
+  length=0;
+  for (i=0; (i < 7U) && (s[i] != '\0'); i++)
+    if (s[i] == ';')
       {
-        o = 3;
-        while (s[o] != ';')
-        {
-          o++;
-          if (o > 5)
-            break;
-        }
-        if (o < 6)
-          (void) strcpy(s+1,s+1+o);
-        *s = val;
-        return o;
+        length=i+1;
+        break;
       }
-    }
-  else
+  if ((length == 0) || (s == (char *) NULL) || (*s == '\0'))
+    return(0);
+  if ((length > 3) && (s[1] == '#') && (sscanf(s,"&#%d;",&value) == 1))
     {
-      int
-        i,
-        codes = (int) (sizeof(html_codes) / sizeof(html_code));
+      size_t
+        o;
 
-      for (i=0; i < codes; i++)
+      o=3;
+      while (s[o] != ';')
       {
-        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);
-              *s = html_codes[i].val;
-              return html_codes[i].len-1;
-            }
+        o++;
+        if (o > 5)
+          break;
       }
+      if (o < 6)
+        (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
+      *s=value;
+      return(o);
     }
-  return 0;
+  {
+    int
+      codes;
+
+    codes=sizeof(html_codes)/sizeof(html_code);
+    for (i=0; i < codes; i++)
+    {
+      if (html_codes[i].len <= length)
+        if (stringnicmp(s,html_codes[i].code,(size_t) (html_codes[i].len)) == 0)
+          {
+            (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);
+          }
+    }
+  }
+  return(0);
 }
 
 static char *super_fgets(char **b, int *blen, Image *file)
@@ -284,7 +298,6 @@ static char *super_fgets(char **b, int *blen, Image *file)
   return((char *) p);
 }
 
-#define BUFFER_SZ 4096
 #define IPTC_ID 1028
 #define THUMBNAIL_ID 1033
 
@@ -309,23 +322,25 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
     recnum;
 
   int
-    inputlen = BUFFER_SZ;
-
-  ssize_t
-    savedolen = 0L,
-    outputlen = 0L;
+    inputlen = MagickPathExtent;
 
   MagickOffsetType
     savedpos,
     currentpos;
 
+  ssize_t
+    savedolen = 0L,
+    outputlen = 0L;
+
   TokenInfo
     *token_info;
 
   dataset = 0;
   recnum = 0;
   line = (char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
-  name = token = (char *)NULL;
+  if (line == (char *) NULL)
+    return(-1);
+  newstr = name = token = (char *) NULL;
   savedpos = 0;
   token_info=AcquireTokenInfo();
   while (super_fgets(&line,&inputlen,ifile)!=NULL)
@@ -334,7 +349,11 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
     next=0;
 
     token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
+    if (token == (char *) NULL)
+      break;
     newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
+    if (newstr == (char *) NULL)
+      break;
     while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
            &brkused,&next,&quoted)==0)
     {
@@ -365,7 +384,7 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
                 recnum = (unsigned int) StringToUnsignedLong(newstr);
                 break;
               case 2:
-                name=(char *) AcquireQuantumMemory(strlen(newstr)+MaxTextExtent,
+                name=(char *) AcquireQuantumMemory(strlen(newstr)+MagickPathExtent,
                   sizeof(*name));
                 if (name)
                   (void) strcpy(name,newstr);
@@ -394,10 +413,17 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
             {
               if (brkused && next > 0)
                 {
+                  size_t
+                    codes_length;
+
                   char
                     *s = &token[next-1];
 
-                  len -= (ssize_t) convertHTMLcodes(s,(int) strlen(s));
+                  codes_length=convertHTMLcodes(s);
+                  if ((ssize_t) codes_length > len)
+                    len=0;
+                  else
+                    len-=codes_length;
                 }
             }
 
@@ -416,13 +442,24 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
 
                     ssize_t diff = outputlen - savedolen;
                     currentpos = TellBlob(ofile);
+                    if (currentpos < 0)
+                      {
+                        line=DestroyString(line);
+                        return(-1);
+                      }
                     offset=SeekBlob(ofile,savedpos,SEEK_SET);
                     if (offset < 0)
-                      return(-1);
+                      {
+                        line=DestroyString(line);
+                        return(-1);
+                      }
                     (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
                     offset=SeekBlob(ofile,currentpos,SEEK_SET);
                     if (offset < 0)
-                      return(-1);
+                      {
+                        line=DestroyString(line);
+                        return(-1);
+                      }
                     savedolen = 0L;
                   }
                 if (outputlen & 1)
@@ -452,7 +489,7 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
 
                     next=0;
                     outputlen += len;
-                    while (len--)
+                    while (len-- > 0)
                       (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
 
                     if (outputlen & 1)
@@ -465,6 +502,8 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
                   {
                     /* patch in a fake length for now and fix it later */
                     savedpos = TellBlob(ofile);
+                    if (savedpos < 0)
+                      return(-1);
                     (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
                     outputlen += 4;
                     savedolen = outputlen;
@@ -481,19 +520,27 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
                     outputlen += 5;
                     next=0;
                     outputlen += len;
-                    while (len--)
+                    while (len-- > 0)
                       (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
                   }
               }
           }
       state++;
     }
-    token=DestroyString(token);
-    newstr=DestroyString(newstr);
+    if (token != (char *) NULL)
+      token=DestroyString(token);
+    if (newstr != (char *) NULL)
+      newstr=DestroyString(newstr);
     if (name != (char *) NULL)
       name=DestroyString(name);
   }
   token_info=DestroyTokenInfo(token_info);
+  if (token != (char *) NULL)
+    token=DestroyString(token);
+  if (newstr != (char *) NULL)
+    newstr=DestroyString(newstr);
+  if (name != (char *) NULL)
+    name=DestroyString(name);
   line=DestroyString(line);
   if (savedolen > 0)
     {
@@ -503,6 +550,8 @@ static ssize_t parse8BIM(Image *ifile, Image *ofile)
       ssize_t diff = outputlen - savedolen;
 
       currentpos = TellBlob(ofile);
+      if (currentpos < 0)
+        return(-1);
       offset=SeekBlob(ofile,savedpos,SEEK_SET);
       if (offset < 0)
         return(-1);
@@ -529,7 +578,7 @@ static char *super_fgets_w(char **b, int *blen, Image *file)
   p=(unsigned char *) (*b);
   for (q=p; ; q++)
   {
-    c=(int) ReadBlobLSBShort(file);
+    c=ReadBlobLSBSignedShort(file);
     if ((c == -1) || (c == '\n'))
       break;
    if (EOFBlob(file))
@@ -585,7 +634,7 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
     recnum;
 
   int
-    inputlen = BUFFER_SZ;
+    inputlen = MagickPathExtent;
 
   ssize_t
     savedolen = 0L,
@@ -601,7 +650,9 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
   dataset = 0;
   recnum = 0;
   line=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
-  name = token = (char *)NULL;
+  if (line == (char *) NULL)
+    return(-1);
+  newstr = name = token = (char *) NULL;
   savedpos = 0;
   token_info=AcquireTokenInfo();
   while (super_fgets_w(&line,&inputlen,ifile) != NULL)
@@ -610,7 +661,11 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
     next=0;
 
     token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
+    if (token == (char *) NULL)
+      break;
     newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
+    if (newstr == (char *) NULL)
+      break;
     while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
       &brkused,&next,&quoted)==0)
     {
@@ -641,10 +696,10 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
                 recnum=(unsigned int) StringToUnsignedLong(newstr);
                 break;
               case 2:
-                name=(char *) AcquireQuantumMemory(strlen(newstr)+MaxTextExtent,
+                name=(char *) AcquireQuantumMemory(strlen(newstr)+MagickPathExtent,
                   sizeof(*name));
                 if (name)
-                  (void) CopyMagickString(name,newstr,strlen(newstr)+MaxTextExtent);
+                  (void) CopyMagickString(name,newstr,strlen(newstr)+MagickPathExtent);
                 break;
             }
             state++;
@@ -670,10 +725,17 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
             {
               if (brkused && next > 0)
                 {
+                  size_t
+                    codes_length;
+
                   char
                     *s = &token[next-1];
 
-                  len -= (ssize_t) convertHTMLcodes(s,(int) strlen(s));
+                  codes_length=convertHTMLcodes(s);
+                  if ((ssize_t) codes_length > len)
+                    len=0;
+                  else
+                    len-=codes_length;
                 }
             }
 
@@ -692,6 +754,8 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
 
                     ssize_t diff = outputlen - savedolen;
                     currentpos = TellBlob(ofile);
+                    if (currentpos < 0)
+                      return(-1);
                     offset=SeekBlob(ofile,savedpos,SEEK_SET);
                     if (offset < 0)
                       return(-1);
@@ -741,6 +805,8 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
                   {
                     /* patch in a fake length for now and fix it later */
                     savedpos = TellBlob(ofile);
+                    if (savedpos < 0)
+                      return(-1);
                     (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
                     outputlen += 4;
                     savedolen = outputlen;
@@ -764,11 +830,20 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
           }
       state++;
     }
+    if (token != (char *) NULL)
+      token=DestroyString(token);
+    if (newstr != (char *) NULL)
+      newstr=DestroyString(newstr);
+    if (name != (char *) NULL)
+      name=DestroyString(name);
+  }
+  token_info=DestroyTokenInfo(token_info);
+  if (token != (char *) NULL)
     token=DestroyString(token);
+  if (newstr != (char *) NULL)
     newstr=DestroyString(newstr);
+  if (name != (char *) NULL)
     name=DestroyString(name);
-  }
-  token_info=DestroyTokenInfo(token_info);
   line=DestroyString(line);
   if (savedolen > 0)
     {
@@ -778,6 +853,8 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
       ssize_t diff = outputlen - savedolen;
 
       currentpos = TellBlob(ofile);
+      if (currentpos < 0)
+        return(-1);
       offset=SeekBlob(ofile,savedpos,SEEK_SET);
       if (offset < 0)
         return(-1);
@@ -787,7 +864,7 @@ static ssize_t parse8BIMW(Image *ifile, Image *ofile)
         return(-1);
       savedolen = 0L;
     }
-  return outputlen;
+  return(outputlen);
 }
 
 /* some defines for the different JPEG block types */
@@ -866,7 +943,7 @@ static int jpeg_skip_variable(Image *ifile, Image *ofile)
   if ((c2 = jpeg_transfer_1(ifile, ofile)) == EOF)
     return M_EOI;
 
-  length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
+  length = (((unsigned int) c1) << 8) + ((unsigned int) c2);
   length -= 2;
 
   while (length--)
@@ -885,7 +962,7 @@ static int jpeg_skip_variable2(Image *ifile, Image *ofile)
   if ((c1 = ReadBlobByte(ifile)) == EOF) return M_EOI;
   if ((c2 = ReadBlobByte(ifile)) == EOF) return M_EOI;
 
-  length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
+  length = (((unsigned int) c1) << 8) + ((unsigned int) c2);
   length -= 2;
 
   while (length--)
@@ -950,8 +1027,6 @@ static int jpeg_skip_till_marker(Image *ifile, int marker)
 }
 #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)
 {
@@ -992,8 +1067,11 @@ static int jpeg_embed(Image *ifile, Image *ofile, Image *iptc)
         /* APP0 is in each and every JPEG, so when we hit APP0 we insert our new APP13! */
         jpeg_skip_variable(ifile, ofile);
 
-        if (iptc != (Image *)NULL)
+        if (iptc != (Image *) NULL)
           {
+            char
+              psheader[] = "\xFF\xED\0\0Photoshop 3.0\0" "8BIM\x04\x04\0\0\0\0";
+
             len=(unsigned int) GetBlobSize(iptc);
             if (len & 1)
               len++; /* make the length even */
@@ -1061,6 +1139,39 @@ static int jpeg_extract(Image *ifile, Image *ofile)
 }
 #endif
 
+static inline void CopyBlob(Image *source,Image *destination)
+{
+  ssize_t
+    i;
+
+  unsigned char
+    *buffer;
+
+  ssize_t
+    count,
+    length;
+
+  buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
+    sizeof(*buffer));
+  if (buffer != (unsigned char *) NULL)
+    {
+      i=0;
+      while ((length=ReadBlob(source,MagickMaxBufferExtent,buffer)) != 0)
+      {
+        count=0;
+        for (i=0; i < (ssize_t) length; i+=count)
+        {
+          count=WriteBlob(destination,(size_t) (length-i),buffer+i);
+          if (count <= 0)
+            break;
+        }
+        if (i < (ssize_t) length)
+          break;
+      }
+      buffer=(unsigned char *) RelinquishMagickMemory(buffer);
+    }
+}
+
 static Image *ReadMETAImage(const ImageInfo *image_info,
   ExceptionInfo *exception)
 {
@@ -1068,9 +1179,6 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
     *buff,
     *image;
 
-  int
-    c;
-
   MagickBooleanType
     status;
 
@@ -1087,13 +1195,13 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
     Open file containing binary metadata
   */
   assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
+  assert(image_info->signature == MagickCoreSignature);
   if (image_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       image_info->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  image=AcquireImage(image_info);
+  assert(exception->signature == MagickCoreSignature);
+  image=AcquireImage(image_info,exception);
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
     {
@@ -1102,9 +1210,8 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
     }
   image->columns=1;
   image->rows=1;
-  if (SetImageBackgroundColor(image) == MagickFalse)
+  if (SetImageBackgroundColor(image,exception) == MagickFalse)
     {
-      InheritException(exception,&image->exception);
       image=DestroyImageList(image);
       return((Image *) NULL);
     }
@@ -1114,7 +1221,7 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
       /*
         Read 8BIM binary metadata.
       */
-      buff=AcquireImage((ImageInfo *) NULL);
+      buff=AcquireImage((ImageInfo *) NULL,exception);
       if (buff == (Image *) NULL)
         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
       blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
@@ -1123,46 +1230,60 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
           buff=DestroyImage(buff);
           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
+      (void) memset(blob,0,length);
       AttachBlob(buff->blob,blob,length);
       if (LocaleCompare(image_info->magick,"8BIMTEXT") == 0)
         {
           length=(size_t) parse8BIM(image, buff);
+          if (length == 0)
+            {
+              blob=DetachBlob(buff->blob);
+              blob=(unsigned char *) RelinquishMagickMemory(blob);
+              buff=DestroyImage(buff);
+              ThrowReaderException(CorruptImageError,"CorruptImage");
+            }
           if (length & 1)
             (void) WriteBlobByte(buff,0x0);
         }
       else if (LocaleCompare(image_info->magick,"8BIMWTEXT") == 0)
         {
           length=(size_t) parse8BIMW(image, buff);
+          if (length == 0)
+            {
+              blob=DetachBlob(buff->blob);
+              blob=(unsigned char *) RelinquishMagickMemory(blob);
+              buff=DestroyImage(buff);
+              ThrowReaderException(CorruptImageError,"CorruptImage");
+            }
           if (length & 1)
             (void) WriteBlobByte(buff,0x0);
         }
       else
+        CopyBlob(image,buff);
+      profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
+        GetBlobSize(buff));
+      if (profile == (StringInfo *) NULL)
         {
-          for ( ; ; )
-          {
-            c=ReadBlobByte(image);
-            if (c == EOF)
-              break;
-            (void) WriteBlobByte(buff,(unsigned char) c);
-          }
+          blob=DetachBlob(buff->blob);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          buff=DestroyImage(buff);
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
-      profile=AcquireStringInfo((size_t) GetBlobSize(buff));
-      SetStringInfoDatum(profile,GetBlobStreamData(buff));
-      status=SetImageProfile(image,"8bim",profile);
+      status=SetImageProfile(image,"8bim",profile,exception);
       profile=DestroyStringInfo(profile);
-      if (status == MagickFalse)
-        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
       blob=DetachBlob(buff->blob);
       blob=(unsigned char *) RelinquishMagickMemory(blob);
       buff=DestroyImage(buff);
+      if (status == MagickFalse)
+        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
     }
   if (LocaleNCompare(image_info->magick,"APP1",4) == 0)
     {
       char
-        name[MaxTextExtent];
+        name[MagickPathExtent];
 
-      (void) FormatMagickString(name,MaxTextExtent,"APP%d",1);
-      buff=AcquireImage((ImageInfo *) NULL);
+      (void) FormatLocaleString(name,MagickPathExtent,"APP%d",1);
+      buff=AcquireImage((ImageInfo *) NULL,exception);
       if (buff == (Image *) NULL)
         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
       blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
@@ -1183,16 +1304,16 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
           if (image_info->profile == (void *) NULL)
             {
               blob=DetachBlob(buff->blob);
-              blob=RelinquishMagickMemory(blob);
+              blob=(unsigned char *) RelinquishMagickMemory(blob);
               buff=DestroyImage(buff);
               ThrowReaderException(CoderError,"NoIPTCProfileAvailable");
             }
           profile=CloneStringInfo((StringInfo *) image_info->profile);
-          iptc=AcquireImage((ImageInfo *) NULL);
+          iptc=AcquireImage((ImageInfo *) NULL,exception);
           if (iptc == (Image *) NULL)
             {
               blob=DetachBlob(buff->blob);
-              blob=RelinquishMagickMemory(blob);
+              blob=(unsigned char *) RelinquishMagickMemory(blob);
               buff=DestroyImage(buff);
               ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
             }
@@ -1200,73 +1321,37 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
             GetStringInfoLength(profile));
           result=jpeg_embed(image,buff,iptc);
           blob=DetachBlob(iptc->blob);
-          blob=RelinquishMagickMemory(blob);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
           iptc=DestroyImage(iptc);
           if (result == 0)
             {
-              blob=DetachBlob(buff->blob);
-              blob=RelinquishMagickMemory(blob);
               buff=DestroyImage(buff);
               ThrowReaderException(CoderError,"JPEGEmbeddingFailed");
             }
         }
       else
+        CopyBlob(image,buff);
+      profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
+        GetBlobSize(buff));
+      if (profile == (StringInfo *) NULL)
         {
-#ifdef SLOW_METHOD
-          for ( ; ; )
-          {
-            /* Really - really slow - FIX ME PLEASE!!!! */
-            c=ReadBlobByte(image);
-            if (c == EOF)
-              break;
-            (void) WriteBlobByte(buff,c);
-          }
-#else
-          ssize_t
-            i;
-
-          unsigned char
-            *buffer;
-
-          ssize_t
-            count,
-            length;
-
-          buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
-            sizeof(*buffer));
-          if (buffer != (unsigned char *) NULL)
-            {
-              i=0;
-              while ((length=ReadBlob(image,MagickMaxBufferExtent,buffer)) != 0)
-              {
-                count=0;
-                for (i=0; i < (ssize_t) length; i+=count)
-                {
-                  count=WriteBlob(buff,(size_t) (length-i),buffer+i);
-                  if (count <= 0)
-                    break;
-                }
-                if (i < (ssize_t) length)
-                  break;
-              }
-              buffer=(unsigned char *) RelinquishMagickMemory(buffer);
-            }
-#endif
+          blob=DetachBlob(buff->blob);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          buff=DestroyImage(buff);
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
-      profile=AcquireStringInfo((size_t) GetBlobSize(buff));
-      SetStringInfoDatum(profile,GetBlobStreamData(buff));
-      status=SetImageProfile(image,name,profile);
+      status=SetImageProfile(image,name,profile,exception);
       profile=DestroyStringInfo(profile);
-      if (status == MagickFalse)
-        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
       blob=DetachBlob(buff->blob);
-      blob=RelinquishMagickMemory(blob);
+      blob=(unsigned char *) RelinquishMagickMemory(blob);
       buff=DestroyImage(buff);
+      if (status == MagickFalse)
+        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
     }
   if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
       (LocaleCompare(image_info->magick,"ICM") == 0))
     {
-      buff=AcquireImage((ImageInfo *) NULL);
+      buff=AcquireImage((ImageInfo *) NULL,exception);
       if (buff == (Image *) NULL)
         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
       blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
@@ -1276,16 +1361,17 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
       AttachBlob(buff->blob,blob,length);
-      for ( ; ; )
-      {
-        c=ReadBlobByte(image);
-        if (c == EOF)
-          break;
-        (void) WriteBlobByte(buff,(unsigned char) c);
-      }
-      profile=AcquireStringInfo((size_t) GetBlobSize(buff));
-      SetStringInfoDatum(profile,GetBlobStreamData(buff));
-      (void) SetImageProfile(image,"icc",profile);
+      CopyBlob(image,buff);
+      profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
+        GetBlobSize(buff));
+      if (profile == (StringInfo *) NULL)
+        {
+          blob=DetachBlob(buff->blob);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          buff=DestroyImage(buff);
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        }
+      (void) SetImageProfile(image,"icc",profile,exception);
       profile=DestroyStringInfo(profile);
       blob=DetachBlob(buff->blob);
       blob=(unsigned char *) RelinquishMagickMemory(blob);
@@ -1293,10 +1379,7 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
     }
   if (LocaleCompare(image_info->magick,"IPTC") == 0)
     {
-      register unsigned char
-        *p;
-
-      buff=AcquireImage((ImageInfo *) NULL);
+      buff=AcquireImage((ImageInfo *) NULL,exception);
       if (buff == (Image *) NULL)
         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
       blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
@@ -1306,38 +1389,17 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
       AttachBlob(buff->blob,blob,length);
-      /* write out the header - length field patched below */
-      (void) WriteBlob(buff,11,(unsigned char *) "8BIM\04\04\0\0\0\0\01");
-      (void) WriteBlobByte(buff,0xe0);
-      if (LocaleCompare(image_info->magick,"IPTCTEXT") == 0)
-        {
-          length=(size_t) parse8BIM(image,buff);
-          if (length & 1)
-            (void) WriteBlobByte(buff,0x00);
-        }
-      else if (LocaleCompare(image_info->magick,"IPTCWTEXT") == 0)
-        {
-        }
-      else
+      CopyBlob(image,buff);
+      profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
+        GetBlobSize(buff));
+      if (profile == (StringInfo *) NULL)
         {
-          for ( ; ; )
-          {
-            c=ReadBlobByte(image);
-            if (c == EOF)
-              break;
-            (void) WriteBlobByte(buff,(unsigned char) c);
-          }
+          blob=DetachBlob(buff->blob);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          buff=DestroyImage(buff);
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
-      profile=AcquireStringInfo((size_t) GetBlobSize(buff));
-      /*
-        subtract off the length of the 8BIM stuff.
-      */
-      length=GetStringInfoLength(profile)-12;
-      p=GetStringInfoDatum(profile);
-      p[10]=(unsigned char) (length >> 8);
-      p[11]=(unsigned char) (length & 0xff);
-      SetStringInfoDatum(profile,GetBlobStreamData(buff));
-      (void) SetImageProfile(image,"8bim",profile);
+      (void) SetImageProfile(image,"8bim",profile,exception);
       profile=DestroyStringInfo(profile);
       blob=DetachBlob(buff->blob);
       blob=(unsigned char *) RelinquishMagickMemory(blob);
@@ -1345,7 +1407,7 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
     }
   if (LocaleCompare(image_info->magick,"XMP") == 0)
     {
-      buff=AcquireImage((ImageInfo *) NULL);
+      buff=AcquireImage((ImageInfo *) NULL,exception);
       if (buff == (Image *) NULL)
         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
       blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
@@ -1355,16 +1417,17 @@ static Image *ReadMETAImage(const ImageInfo *image_info,
           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
       AttachBlob(buff->blob,blob,length);
-      for ( ; ; )
-      {
-        c=ReadBlobByte(image);
-        if (c == EOF)
-          break;
-        (void) WriteBlobByte(buff,(unsigned char) c);
-      }
-      profile=AcquireStringInfo((size_t) GetBlobSize(buff));
-      SetStringInfoDatum(profile,GetBlobStreamData(buff));
-      (void) SetImageProfile(image,"xmp",profile);
+      CopyBlob(image,buff);
+      profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
+        GetBlobSize(buff));
+      if (profile == (StringInfo *) NULL)
+        {
+          blob=DetachBlob(buff->blob);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          buff=DestroyImage(buff);
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        }
+      (void) SetImageProfile(image,"xmp",profile,exception);
       profile=DestroyStringInfo(profile);
       blob=DetachBlob(buff->blob);
       blob=(unsigned char *) RelinquishMagickMemory(blob);
@@ -1402,124 +1465,90 @@ ModuleExport size_t RegisterMETAImage(void)
   MagickInfo
     *entry;
 
-  entry=SetMagickInfo("8BIM");
+  entry=AcquireMagickInfo("META","8BIM","Photoshop resource format");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Photoshop resource format");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("8BIMTEXT");
+  entry=AcquireMagickInfo("META","8BIMTEXT","Photoshop resource text format");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Photoshop resource text format");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("8BIMWTEXT");
+  entry=AcquireMagickInfo("META","8BIMWTEXT",
+    "Photoshop resource wide text format");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Photoshop resource wide text format");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("APP1");
+  entry=AcquireMagickInfo("META","APP1","Raw application information");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Raw application information");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("APP1JPEG");
+  entry=AcquireMagickInfo("META","APP1JPEG","Raw JPEG binary data");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Raw JPEG binary data");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("EXIF");
+  entry=AcquireMagickInfo("META","EXIF","Exif digital camera binary data");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Exif digital camera binary data");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("XMP");
+  entry=AcquireMagickInfo("META","XMP","Adobe XML metadata");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Adobe XML metadata");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("ICM");
+  entry=AcquireMagickInfo("META","ICM","ICC Color Profile");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("ICC Color Profile");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("ICC");
+  entry=AcquireMagickInfo("META","ICC","ICC Color Profile");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("ICC Color Profile");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("IPTC");
+  entry=AcquireMagickInfo("META","IPTC","IPTC Newsphoto");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("IPTC Newsphoto");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("IPTCTEXT");
+  entry=AcquireMagickInfo("META","IPTCTEXT","IPTC Newsphoto text format");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("IPTC Newsphoto text format");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
-
-  entry=SetMagickInfo("IPTCWTEXT");
+  entry=AcquireMagickInfo("META","IPTCWTEXT","IPTC Newsphoto text format");
   entry->decoder=(DecodeImageHandler *) ReadMETAImage;
   entry->encoder=(EncodeImageHandler *) WriteMETAImage;
-  entry->adjoin=MagickFalse;
-  entry->stealth=MagickTrue;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("IPTC Newsphoto text format");
-  entry->module=ConstantString("META");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderStealthFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);
 }
@@ -1576,7 +1605,7 @@ ModuleExport void UnregisterMETAImage(void)
 %  The format of the WriteMETAImage method is:
 %
 %      MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
-%        Image *image)
+%        Image *image,ExceptionInfo *exception)
 %
 %  Compression code contributed by Kyle Shorter.
 %
@@ -1586,6 +1615,8 @@ ModuleExport void UnregisterMETAImage(void)
 %
 %    o image: A pointer to a Image structure.
 %
+%    o exception: return any errors or warnings in this structure.
+%
 */
 
 static size_t GetIPTCStream(unsigned char **info,size_t length)
@@ -1603,9 +1634,6 @@ static size_t GetIPTCStream(unsigned char **info,size_t length)
     extent,
     info_length;
 
-  unsigned char
-    buffer[4] = { '\0', '\0', '\0', '\0' };
-
   unsigned int
     marker;
 
@@ -1718,27 +1746,32 @@ iptc_find:
     info_length++;
     if ((c & 0x80) != 0)
       {
+        /*
+          Long format.
+        */
+        tag_length=0;
         for (i=0; i < 4; i++)
         {
-          buffer[i]=(*p++);
+          tag_length<<=8;
+          tag_length|=(*p++);
           length--;
           if (length == 0)
             break;
           info_length++;
         }
-        tag_length=(((size_t) buffer[0]) << 24) |
-          (((size_t) buffer[1]) << 16) |
-          (((size_t) buffer[2]) << 8) | (((size_t) buffer[3])); 
       }
     else
       {
-        tag_length=(size_t) (c << 8);
+        /*
+          Short format.
+        */
+        tag_length=((long) c) << 8;
         c=(*p++);
         length--;
         if (length == 0)
           break;
         info_length++;
-        tag_length|=c;
+        tag_length|=(long) c;
       }
     if (tag_length > (length+1))
       break;
@@ -1754,7 +1787,7 @@ iptc_find:
 static void formatString(Image *ofile, const char *s, int len)
 {
   char
-    temp[MaxTextExtent];
+    temp[MagickPathExtent];
 
   (void) WriteBlobByte(ofile,'"');
   for (; len > 0; len--, s++) {
@@ -1779,7 +1812,7 @@ static void formatString(Image *ofile, const char *s, int len)
         (void) WriteBlobByte(ofile,(unsigned char) *s);
       else
         {
-          (void) FormatMagickString(temp,MaxTextExtent,"&#%d;", c & 255);
+          (void) FormatLocaleString(temp,MagickPathExtent,"&#%d;", c & 255);
           (void) WriteBlobString(ofile,temp);
         }
       break;
@@ -1798,7 +1831,7 @@ static void formatString(Image *ofile, const char *s, int len)
 
 typedef struct _tag_spec
 {
-  short
+  const short
     id;
 
   const char
@@ -1827,6 +1860,7 @@ static const tag_spec tags[] = {
   { 80, "Byline" },
   { 85, "Byline Title" },
   { 90, "City" },
+  { 92, "Sub-Location" },
   { 95, "Province State" },
   { 100, "Country Code" },
   { 101, "Country" },
@@ -1864,7 +1898,7 @@ static const tag_spec tags[] = {
 static int formatIPTC(Image *ifile, Image *ofile)
 {
   char
-    temp[MaxTextExtent];
+    temp[MagickPathExtent];
 
   unsigned int
     foundiptc,
@@ -1900,17 +1934,22 @@ static int formatIPTC(Image *ifile, Image *ofile)
     else
       {
         if (foundiptc)
-          return -1;
+          return(-1);
         else
-          continue;
+          {
+            c=0;
+            continue;
+          }
       }
 
     /* we found the 0x1c tag and now grab the dataset and record number tags */
     c = ReadBlobByte(ifile);
-    if (c == EOF) return -1;
+    if (c == EOF)
+      return(-1);
     dataset = (unsigned char) c;
     c = ReadBlobByte(ifile);
-    if (c == EOF) return -1;
+    if (c == EOF)
+      return(-1);
     recnum = (unsigned char) c;
     /* try to match this record to one of the ones in our named table */
     for (i=0; i< tagcount; i++)
@@ -1926,41 +1965,45 @@ static int formatIPTC(Image *ifile, Image *ofile)
       We decode the length of the block that follows - ssize_t or short fmt.
     */
     c=ReadBlobByte(ifile);
-    if (c == EOF) return -1;
+    if (c == EOF)
+      return(-1);
     if (c & (unsigned char) 0x80)
-      return 0;
+      return(0);
     else
       {
         int
           c0;
 
         c0=ReadBlobByte(ifile);
-        if (c0 == EOF) return -1;
+        if (c0 == EOF)
+          return(-1);
         taglen = (c << 8) | c0;
       }
-    if (taglen < 0) return -1;
+    if (taglen < 0)
+      return(-1);
     /* make a buffer to hold the tag datand snag it from the input stream */
-    str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+MaxTextExtent),
-      sizeof(*str));
+    str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+
+      MagickPathExtent),sizeof(*str));
     if (str == (unsigned char *) NULL)
-      {
-        printf("MemoryAllocationFailed");
-        return 0;
-      }
+      return(0);
     for (tagindx=0; tagindx<taglen; tagindx++)
     {
       c=ReadBlobByte(ifile);
-      if (c == EOF) return -1;
+      if (c == EOF)
+        {
+          str=(unsigned char *) RelinquishMagickMemory(str);
+          return(-1);
+        }
       str[tagindx] = (unsigned char) c;
     }
     str[taglen] = 0;
 
     /* now finish up by formatting this binary data into ASCII equivalent */
     if (strlen((char *)readable) > 0)
-      (void) FormatMagickString(temp,MaxTextExtent,"%d#%d#%s=",
+      (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d#%s=",
         (unsigned int) dataset, (unsigned int) recnum, readable);
     else
-      (void) FormatMagickString(temp,MaxTextExtent,"%d#%d=",
+      (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d=",
         (unsigned int) dataset,(unsigned int) recnum);
     (void) WriteBlobString(ofile,temp);
     formatString( ofile, (char *)str, taglen );
@@ -1995,7 +2038,7 @@ static int readWordFromBuffer(char **s, ssize_t *len)
 static int formatIPTCfromBuffer(Image *ofile, char *s, ssize_t len)
 {
   char
-    temp[MaxTextExtent];
+    temp[MagickPathExtent];
 
   unsigned int
     foundiptc,
@@ -2069,29 +2112,34 @@ static int formatIPTCfromBuffer(Image *ofile, char *s, ssize_t len)
       }
     if (taglen < 0)
       return(-1);
+    if (taglen > 65535)
+      return(-1);
     /* make a buffer to hold the tag datand snag it from the input stream */
-    str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+MaxTextExtent),
-      sizeof(*str));
+    str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+
+      MagickPathExtent),sizeof(*str));
     if (str == (unsigned char *) NULL)
       {
-        printf("MemoryAllocationFailed");
+        (void) printf("MemoryAllocationFailed");
         return 0;
       }
     for (tagindx=0; tagindx<taglen; tagindx++)
     {
       c = *s++; len--;
       if (len < 0)
-        return(-1);
+        {
+          str=(unsigned char *) RelinquishMagickMemory(str);
+          return(-1);
+        }
       str[tagindx]=(unsigned char) c;
     }
     str[taglen]=0;
 
     /* now finish up by formatting this binary data into ASCII equivalent */
     if (strlen((char *)readable) > 0)
-      (void) FormatMagickString(temp,MaxTextExtent,"%d#%d#%s=",
+      (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d#%s=",
         (unsigned int) dataset,(unsigned int) recnum, readable);
     else
-      (void) FormatMagickString(temp,MaxTextExtent,"%d#%d=",
+      (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d=",
         (unsigned int) dataset,(unsigned int) recnum);
     (void) WriteBlobString(ofile,temp);
     formatString( ofile, (char *)str, taglen );
@@ -2105,7 +2153,7 @@ static int formatIPTCfromBuffer(Image *ofile, char *s, ssize_t len)
 static int format8BIM(Image *ifile, Image *ofile)
 {
   char
-    temp[MaxTextExtent];
+    temp[MagickPathExtent];
 
   unsigned int
     foundOSType;
@@ -2125,6 +2173,7 @@ static int format8BIM(Image *ifile, Image *ofile)
 
   resCount=0;
   foundOSType=0; /* found the OSType */
+  (void) foundOSType;
   c=ReadBlobByte(ifile);
   while (c != EOF)
   {
@@ -2155,7 +2204,7 @@ static int format8BIM(Image *ifile, Image *ofile)
     /*
       We found the OSType (8BIM) and now grab the ID, PString, and Size fields.
     */
-    ID=(int) ReadBlobMSBShort(ifile);
+    ID=ReadBlobMSBSignedShort(ifile);
     if (ID < 0)
       return(-1);
     {
@@ -2167,16 +2216,17 @@ static int format8BIM(Image *ifile, Image *ofile)
         return(-1);
       plen = (unsigned char) c;
       PString=(unsigned char *) AcquireQuantumMemory((size_t) (plen+
-        MaxTextExtent),sizeof(*PString));
+        MagickPathExtent),sizeof(*PString));
       if (PString == (unsigned char *) NULL)
-        {
-          printf("MemoryAllocationFailed");
-          return 0;
-        }
+        return 0;
       for (i=0; i<plen; i++)
       {
         c=ReadBlobByte(ifile);
-        if (c == EOF) return -1;
+        if (c == EOF)
+          {
+            PString=(unsigned char *) RelinquishMagickMemory(PString);
+            return -1;
+          }
         PString[i] = (unsigned char) c;
       }
       PString[ plen ] = 0;
@@ -2184,23 +2234,34 @@ static int format8BIM(Image *ifile, Image *ofile)
       {
         c=ReadBlobByte(ifile);
         if (c == EOF)
-          return(-1);
+          {
+            PString=(unsigned char *) RelinquishMagickMemory(PString);
+            return -1;
+          }
       }
     }
-    count = (ssize_t) ReadBlobMSBLong(ifile);
-    if (count < 0) return -1;
-    /* make a buffer to hold the datand snag it from the input stream */
-    str=(unsigned char *) AcquireQuantumMemory((size_t) count,sizeof(*str));
+    count=(ssize_t) ReadBlobMSBSignedLong(ifile);
+    if ((count < 0) || (count > GetBlobSize(ifile)))
+      {
+        PString=(unsigned char *) RelinquishMagickMemory(PString);
+        return -1;
+      }
+    /* make a buffer to hold the data and snag it from the input stream */
+    str=(unsigned char *) AcquireQuantumMemory((size_t) count+1,sizeof(*str));
     if (str == (unsigned char *) NULL)
       {
-        printf("MemoryAllocationFailed");
+        PString=(unsigned char *) RelinquishMagickMemory(PString);
         return 0;
       }
     for (i=0; i < (ssize_t) count; i++)
     {
       c=ReadBlobByte(ifile);
       if (c == EOF)
-        return(-1);
+        {
+          str=(unsigned char *) RelinquishMagickMemory(str);
+          PString=(unsigned char *) RelinquishMagickMemory(PString);
+          return -1;
+        }
       str[i]=(unsigned char) c;
     }
 
@@ -2213,10 +2274,10 @@ static int format8BIM(Image *ifile, Image *ofile)
          * ASCII equivalent
          */
         if (strlen((const char *)PString) > 0)
-          (void) FormatMagickString(temp,MaxTextExtent,"8BIM#%d#%s=",ID,
+          (void) FormatLocaleString(temp,MagickPathExtent,"8BIM#%d#%s=",ID,
             PString);
         else
-          (void) FormatMagickString(temp,MaxTextExtent,"8BIM#%d=",ID);
+          (void) FormatLocaleString(temp,MagickPathExtent,"8BIM#%d=",ID);
         (void) WriteBlobString(ofile,temp);
         if (ID == IPTC_ID)
           {
@@ -2235,7 +2296,7 @@ static int format8BIM(Image *ifile, Image *ofile)
 }
 
 static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
-  Image *image)
+  Image *image,ExceptionInfo *exception)
 {
   const StringInfo
     *profile;
@@ -2250,9 +2311,9 @@ static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
     Open image file.
   */
   assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
+  assert(image_info->signature == MagickCoreSignature);
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   length=0;
@@ -2264,7 +2325,9 @@ static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
       profile=GetImageProfile(image,"8bim");
       if (profile == (StringInfo *) NULL)
         ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
-      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+      assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickCoreSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
       if (status == MagickFalse)
         return(status);
       (void) WriteBlob(image,GetStringInfoLength(profile),
@@ -2280,10 +2343,14 @@ static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
       unsigned char
         *info;
 
-      profile=GetImageProfile(image,"8bim");
+      profile=GetImageProfile(image,"iptc");
+      if (profile == (StringInfo *) NULL)
+        profile=GetImageProfile(image,"8bim");
       if (profile == (StringInfo *) NULL)
         ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
-      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+      assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickCoreSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
       info=GetStringInfoDatum(profile);
       length=GetStringInfoLength(profile);
       length=GetIPTCStream(&info,length);
@@ -2301,10 +2368,12 @@ static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
       profile=GetImageProfile(image,"8bim");
       if (profile == (StringInfo *) NULL)
         ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
-      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+      assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickCoreSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
       if (status == MagickFalse)
         return(status);
-      buff=AcquireImage((ImageInfo *) NULL);
+      buff=AcquireImage((ImageInfo *) NULL,exception);
       if (buff == (Image *) NULL)
         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
       AttachBlob(buff->blob,GetStringInfoDatum(profile),
@@ -2333,10 +2402,12 @@ static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
       length=GetIPTCStream(&info,length);
       if (length == 0)
         ThrowWriterException(CoderError,"NoIPTCProfileAvailable");
-      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+      assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickCoreSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
       if (status == MagickFalse)
         return(status);
-      buff=AcquireImage((ImageInfo *) NULL);
+      buff=AcquireImage((ImageInfo *) NULL,exception);
       if (buff == (Image *) NULL)
         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
       AttachBlob(buff->blob,info,length);
@@ -2358,7 +2429,9 @@ static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
       profile=GetImageProfile(image,image_info->magick);
       if (profile == (StringInfo *) NULL)
         ThrowWriterException(CoderError,"NoAPP1DataIsAvailable");
-      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+      assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickCoreSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
       if (status == MagickFalse)
         return(status);
       (void) WriteBlob(image,GetStringInfoLength(profile),
@@ -2375,7 +2448,9 @@ static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
       profile=GetImageProfile(image,"icc");
       if (profile == (StringInfo *) NULL)
         ThrowWriterException(CoderError,"NoColorProfileIsAvailable");
-      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+      assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickCoreSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
       if (status == MagickFalse)
         return(status);
       (void) WriteBlob(image,GetStringInfoLength(profile),