--- GraphicsMagick-1.1.8/magick/delegate.c
+++ GraphicsMagick-1.1.8/magick/delegate.c
@@ -389,7 +389,10 @@
   char
     *command,
     **commands,
-    filename[MaxTextExtent];
+    linkedname[MaxTextExtent],
+    linkedinfoname[MaxTextExtent],
+    filename[MaxTextExtent],
+    safechars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,-_+ /";
 
   const DelegateInfo
     *delegate_info;
@@ -409,6 +412,10 @@
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
   temporary_image_filename=(*image->filename == '\0');
+  linkedname[0]='\0';
+  linkedname[MaxTextExtent-1]='\0';
+  linkedinfoname[0]='\0';
+  linkedinfoname[MaxTextExtent-1]='\0';
   if (temporary_image_filename)
     {
       /* Allocate a temporary filename if image is unnamed.  */
@@ -418,12 +425,24 @@
           return(False);
         }
     }
+  else if (strspn(image->filename, safechars) != strlen(image->filename))
+    {
+      strncpy(linkedname,image->filename,MaxTextExtent-1);
+      if (!AcquireTemporarySymlink(image->filename,linkedname))
+	{
+          (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image->filename);
+	  return (False);
+	}
+    }
+
   (void) strlcpy(filename,image->filename,MaxTextExtent);
   delegate_info=GetDelegateInfo(decode,encode,exception);
   if (delegate_info == (DelegateInfo *) NULL)
     {
       if (temporary_image_filename)
         (void) LiberateTemporaryFile(image->filename);
+      if (*linkedname)
+	strncpy(image->filename,linkedname,MaxTextExtent-1);
       (void) ThrowException(exception,DelegateError,NoTagFound,
         decode ? decode : encode);
       return(False);
@@ -444,6 +463,18 @@
         }
       image_info->temporary=True;
     }
+  else if (strspn(image_info->filename, safechars) != strlen(image_info->filename))
+    {
+      strncpy(linkedinfoname,image_info->filename,MaxTextExtent-1);
+      if (!AcquireTemporarySymlink(image_info->filename,linkedinfoname))
+	{
+          if (temporary_image_filename)
+            LiberateTemporaryFile(image->filename);
+          (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->filename);
+          return(False);
+        }
+      temporary_image_filename=True;
+    }
 
   if (delegate_info->mode != 0)
     if ((decode && (delegate_info->encode != (char *) NULL)) ||
@@ -467,6 +498,13 @@
         {
           if (temporary_image_filename)
             (void) LiberateTemporaryFile(image->filename);
+	  if (*linkedname)
+            strncpy(image->filename,linkedname,MaxTextExtent-1);
+	  if (*linkedinfoname)
+            {
+              LiberateTemporaryFile(linkedinfoname);
+              strncpy(image_info->filename,linkedinfoname,MaxTextExtent-1);
+	    }
           (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->unique);
           return(False);
         }
@@ -475,6 +513,13 @@
         {
           if (temporary_image_filename)
             (void) LiberateTemporaryFile(image->filename);
+	  if (*linkedname)
+            strncpy(image->filename,linkedname,MaxTextExtent-1);
+	  if (*linkedinfoname)
+            {
+              LiberateTemporaryFile(linkedinfoname);
+              strncpy(image_info->filename,linkedinfoname,MaxTextExtent-1);
+	    }
           (void) LiberateTemporaryFile(image_info->unique);
           (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->zero);
           return(False);
@@ -488,6 +533,13 @@
             (void) LiberateTemporaryFile(image_info->zero);
             if (temporary_image_filename)
               (void) LiberateTemporaryFile(image->filename);
+	    if (*linkedname)
+              strncpy(image->filename,linkedname,MaxTextExtent-1);
+	    if (*linkedinfoname)
+              {
+                LiberateTemporaryFile(linkedinfoname);
+                strncpy(image_info->filename,linkedinfoname,MaxTextExtent-1);
+	      }
             (void) ThrowException(exception,DelegateError,DelegateFailed,
               decode ? decode : encode);
             return(False);
@@ -513,6 +565,13 @@
               (void) LiberateTemporaryFile(image_info->zero);
               if (temporary_image_filename)
                 (void) LiberateTemporaryFile(image->filename);
+	      if (*linkedname)
+                strncpy(image->filename,linkedname,MaxTextExtent-1);
+	      if (*linkedinfoname)
+                {
+                  LiberateTemporaryFile(linkedinfoname);
+                  strncpy(image_info->filename,linkedinfoname,MaxTextExtent-1);
+	        }
               DestroyImageInfo(clone_info);
               (void) ThrowException(exception,DelegateError,DelegateFailed,
                 decode ? decode : encode);
@@ -534,6 +593,13 @@
     {
       if (temporary_image_filename)
         (void) LiberateTemporaryFile(image->filename);
+      if (*linkedname)
+        strncpy(image->filename,linkedname,MaxTextExtent-1);
+      if (*linkedinfoname)
+        {
+          LiberateTemporaryFile(linkedinfoname);
+          strncpy(image_info->filename,linkedinfoname,MaxTextExtent-1);
+        }
       (void) ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,decode ? decode : encode);
       return(False);
     }
@@ -668,6 +734,13 @@
  error_exit:
   if (temporary_image_filename)
     (void) LiberateTemporaryFile(image->filename);
+  if (*linkedname)
+    strncpy(image->filename,linkedname,MaxTextExtent-1);
+  if (*linkedinfoname)
+    {
+      LiberateTemporaryFile(linkedinfoname);
+      strncpy(image_info->filename,linkedinfoname,MaxTextExtent-1);
+    }
   for ( ; commands[i] != (char *) NULL; i++)
     MagickFreeMemory(commands[i]);
   MagickFreeMemory(commands);
--- GraphicsMagick-1.1.8/magick/symbols.h
+++ GraphicsMagick-1.1.8/magick/symbols.h
@@ -30,6 +30,7 @@
 #define AcquireTemporaryFileDescriptor GmAcquireTemporaryFileDescriptor
 #define AcquireTemporaryFileName GmAcquireTemporaryFileName
 #define AcquireTemporaryFileStream GmAcquireTemporaryFileStream
+#define AcquireTemporarySymlink GmAcquireTemporarySymlink
 #define AdaptiveThresholdImage GmAdaptiveThresholdImage
 #define AddDefinitions GmAddDefinitions
 #define AddNoiseImage GmAddNoiseImage
--- GraphicsMagick-1.1.8/magick/tempfile.c
+++ GraphicsMagick-1.1.8/magick/tempfile.c
@@ -197,6 +197,93 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   A c q u i r e T e m p o r a r y S y m l i n k                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% AcquireTemporarySymlink replaces the contents of the string buffer pointed
+% to by filename with the unique name of a symbolic link.  True is returned
+% if a symlink waas created, or False is returned if there is a failure.
+% The allocated symlink should be recovered via the LiberateTemporaryFile()
+% function once it is no longer required.
+%
+% The format of the AcquireTemporarySymlink method is:
+%
+%     unsigned int AcquireTemporarySymlink(char *linkname, const char *name,
+%                                          ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%   o linkname: Specifies a pointer to an array of characters that must be
+%               MaxTextExtent characters of size.  The unique
+%               name of the symlink is returned in this array.
+%   o name: Specifies a file name the symlink should point to.
+*/
+MagickExport unsigned int AcquireTemporarySymlink(char *linkname, const char *name)
+{
+  char
+    *tempdir,
+    tempname[MaxTextExtent];
+
+  int
+    fd,
+    tries;
+  
+  assert(linkname != (char *)NULL);
+  linkname[0]='\0';
+  tempname[MaxTextExtent-1]='\0';
+
+  tempdir=getenv("MAGICK_TMPDIR");
+#if defined(POSIX)
+  if (!tempdir)
+    tempdir=getenv("TMPDIR");
+#endif /* POSIX */
+#if defined(WIN32)
+  if (!tempdir)
+    tempdir=getenv("TMP");
+  if (!tempdir)
+    tempdir=getenv("TEMP");
+#endif /* WIN32 */
+#if defined(P_tmpdir)
+  if (!tempdir)
+    tempdir=P_tmpdir;
+#endif
+
+  for (tries=0; tries < 15; tries++)
+    {
+      strncpy(tempname,"gmXXXXXX",MaxTextExtent-1);
+      ComposeTemporaryFileName(tempname);
+      strncpy(linkname,tempdir,MaxTextExtent-1);
+      if (tempdir[strlen(tempdir)-1] != DirectorySeparator[0])
+	strncat(linkname,DirectorySeparator,MaxTextExtent-1);
+      strncat(linkname,tempname,MaxTextExtent-1);
+      if (*name == '/')
+        fd=symlink(name, linkname);
+      else
+        {
+          char cname[MaxTextExtent];
+	  if (!getcwd(cname,(size_t)MaxTextExtent))
+	    return (False);
+	  strncat(cname,DirectorySeparator,MaxTextExtent-1);
+	  strncat(cname,name,MaxTextExtent-1);
+	  fd=symlink(cname,linkname);
+	}
+      if (fd != -1)
+	{
+	  AddTemporaryFileToList(linkname);
+	  return (True);
+	}
+    }
+  return (False);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +   A c q u i r e T e m p o r a r y F i l e D e s c r i p t o r               %
 %                                                                             %
 %                                                                             %
--- GraphicsMagick-1.1.8/magick/tempfile.h
+++ GraphicsMagick-1.1.8/magick/tempfile.h
@@ -26,6 +26,7 @@
 
 MagickExport unsigned int
   AcquireTemporaryFileName(char *filename),
+  AcquireTemporarySymlink(char *linkname, const char *name),
   LiberateTemporaryFile(char *filename);
 
 MagickExport int
--- GraphicsMagick-1.1.8/magick/utility.c
+++ GraphicsMagick-1.1.8/magick/utility.c
@@ -1134,6 +1134,72 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%  F o r m a t S t r i n g N u m e r i c                                      %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  Method FormatStringNumeric formats output for a single numeric argument.
+%  It takes into account that the format string given might be untrusted
+%  user input, and returns a pointer to the formatted string.
+%
+%  The format of the FormatStringNumeric method is:
+%
+%      char * FormatStringNumeric(char *string,const char *format,int value)
+%
+%  A description of each parameter follows.
+%
+%   o  format:  A string describing the format to use to write the numeric
+%      argument. Only the first numeric format identifier is replaced.
+%
+%   o  value:  Numeric value to substitute into format string.
+%
+%
+*/
+MagickExport char *FormatStringNumeric(const char *format,int value)
+{
+  char
+    *p,
+    *string;
+
+  string = NULL;
+
+  (void) CloneString(&string, format);
+
+  for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
+  {  
+    char
+      *q;
+
+    q=(char *) p+1;
+    if (*q == '0')
+      (void) strtol(q,&q,10);
+    if ((*q == '%') || (*q == 'd') || (*q == 'o') || (*q == 'x'))
+    {
+      char
+        c;
+
+      q++;
+      c=*q;
+      *q='\0';
+      (void) snprintf(string+(p-format),MaxTextExtent-(p-format),p,value);
+      *q=c;
+      (void) ConcatenateString(&string,q);
+      if (*(q-1) == '%')
+        p++;
+      else
+        break;
+    }
+  }
+  return string;
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   G e t E x e c u t i o n P a t h                                           %
 %                                                                             %
 %                                                                             %
--- GraphicsMagick-1.1.8/magick/utility.h
+++ GraphicsMagick-1.1.8/magick/utility.h
@@ -70,6 +70,7 @@
   *AllocateString(const char *),
   *Base64Encode(const unsigned char *,const size_t,size_t *),
   *EscapeString(const char *,const char),
+  *FormatStringNumeric(const char *,int),
   *GetPageGeometry(const char *),
   **ListFiles(const char *,const char *,long *),
   *SetClientName(const char *),
