[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2016-5118

The OpenBlob function in blob.c in GraphicsMagick before 1.3.24 and ImageMagick allows remote attackers to execute arbitrary code via a | (pipe) character at the start of a filename.

## Package
GraphicsMagick

## Files to modify
- GraphicsMagick-1.3.18.orig/magick/utility.c
- magick/tempfile.h
- GraphicsMagick-1.3.18.orig/magick/tempfile.c
- GraphicsMagick-1.3.18.orig/magick/symbols.h
- magick/utility.h

## Upstream Fix
```diff
Index: GraphicsMagick-1.3.18/magick/delegate.c
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/delegate.c
+++ GraphicsMagick-1.3.18/magick/delegate.c
@@ -539,7 +539,10 @@ MagickExport unsigned int InvokeDelegate
   char
     *command,
     **commands,
-    filename[MaxTextExtent];
+    linkedname[MaxTextExtent],
+    linkedinfoname[MaxTextExtent],
+    filename[MaxTextExtent],
+    safechars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,-_+ /";

   const DelegateInfo
     *delegate_info;
@@ -559,6 +562,10 @@ MagickExport unsigned int InvokeDelegate
   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.  */
@@ -568,12 +575,24 @@ MagickExport unsigned int InvokeDelegate
           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);
@@ -594,6 +613,18 @@ MagickExport unsigned int InvokeDelegate
         }
       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)) ||
@@ -617,6 +648,13 @@ MagickExport unsigned int InvokeDelegate
         {
           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);
         }
@@ -625,6 +663,13 @@ MagickExport unsigned int InvokeDelegate
         {
           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);
@@ -638,6 +683,13 @@ MagickExport unsigned int InvokeDelegate
             (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);
@@ -663,6 +715,13 @@ MagickExport unsigned int InvokeDelegate
               (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);
@@ -684,6 +743,13 @@ MagickExport unsigned int InvokeDelegate
     {
       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);
     }
@@ -810,6 +876,13 @@ MagickExport unsigned int InvokeDelegate
  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);
Index: GraphicsMagick-1.3.18/magick/symbols.h
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/symbols.h
+++ GraphicsMagick-1.3.18/magick/symbols.h
@@ -43,6 +43,7 @@
 #define AcquireTemporaryFileDescriptor GmAcquireTemporaryFileDescriptor
 #define AcquireTemporaryFileName GmAcquireTemporaryFileName
 #define AcquireTemporaryFileStream GmAcquireTemporaryFileStream
+#define AcquireTemporarySymlink GmAcquireTemporarySymlink
 #define AdaptiveThresholdImage GmAdaptiveThresholdImage
 #define AddDefinition GmAddDefinition
 #define AddDefinitions GmAddDefinitions
Index: GraphicsMagick-1.3.18/magick/tempfile.c
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/tempfile.c
+++ GraphicsMagick-1.3.18/magick/tempfile.c
@@ -192,6 +192,93 @@ MagickExport MagickPassFail AcquireTempo
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   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
... (truncated)
```

Generate a backported patch for the SUSE target version.

[Assistant]
Index: GraphicsMagick-1.3.18/magick/delegate.c
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/delegate.c
+++ GraphicsMagick-1.3.18/magick/delegate.c
@@ -539,7 +539,10 @@ MagickExport unsigned int InvokeDelegate
   char
     *command,
     **commands,
-    filename[MaxTextExtent];
+    linkedname[MaxTextExtent],
+    linkedinfoname[MaxTextExtent],
+    filename[MaxTextExtent],
+    safechars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,-_+ /";

   const DelegateInfo
     *delegate_info;
@@ -559,6 +562,10 @@ MagickExport unsigned int InvokeDelegate
   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.  */
@@ -568,12 +575,24 @@ MagickExport unsigned int InvokeDelegate
           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);
@@ -594,6 +613,18 @@ MagickExport unsigned int InvokeDelegate
         }
       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)) ||
@@ -617,6 +648,13 @@ MagickExport unsigned int InvokeDelegate
         {
           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);
         }
@@ -625,6 +663,13 @@ MagickExport unsigned int InvokeDelegate
         {
           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);
@@ -638,6 +683,13 @@ MagickExport unsigned int InvokeDelegate
             (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);
@@ -663,6 +715,13 @@ MagickExport unsigned int InvokeDelegate
               (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);
@@ -684,6 +743,13 @@ MagickExport unsigned int InvokeDelegate
     {
       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);
     }
@@ -810,6 +876,13 @@ MagickExport unsigned int InvokeDelegate
  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);
Index: GraphicsMagick-1.3.18/magick/symbols.h
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/symbols.h
+++ GraphicsMagick-1.3.18/magick/symbols.h
@@ -43,6 +43,7 @@
 #define AcquireTemporaryFileDescriptor GmAcquireTemporaryFileDescriptor
 #define AcquireTemporaryFileName GmAcquireTemporaryFileName
 #define AcquireTemporaryFileStream GmAcquireTemporaryFileStream
+#define AcquireTemporarySymlink GmAcquireTemporarySymlink
 #define AdaptiveThresholdImage GmAdaptiveThresholdImage
 #define AddDefinition GmAddDefinition
 #define AddDefinitions GmAddDefinitions
Index: GraphicsMagick-1.3.18/magick/tempfile.c
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/tempfile.c
+++ GraphicsMagick-1.3.18/magick/tempfile.c
@@ -192,6 +192,93 @@ MagickExport MagickPassFail AcquireTempo
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   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               %
 %                                                                             %
 %                                                                             %
Index: GraphicsMagick-1.3.18/magick/tempfile.h
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/tempfile.h
+++ GraphicsMagick-1.3.18/magick/tempfile.h
@@ -24,6 +24,7 @@ typedef enum

 MagickExport MagickPassFail
   AcquireTemporaryFileName(char *filename),
+  AcquireTemporarySymlink(char *linkname, const char *name),
   LiberateTemporaryFile(char *filename);

 MagickExport int
Index: GraphicsMagick-1.3.18/magick/utility.c
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/utility.c
+++ GraphicsMagick-1.3.18/magick/utility.c
@@ -1253,6 +1253,72 @@ MagickExport void FormatString(char *str
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%  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                                           %
 %                                                                             %
 %                                                                             %
Index: GraphicsMagick-1.3.18/magick/utility.h
===================================================================
--- GraphicsMagick-1.3.18.orig/magick/utility.h
+++ GraphicsMagick-1.3.18/magick/utility.h
@@ -72,6 +72,7 @@ extern MagickExport char
   *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 *),
   **StringToArgv(const char *,int *),


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2013-4560

Use-after-free vulnerability in lighttpd before 1.4.33 allows remote attackers to cause a denial of service (segmentation fault and crash) via unspecified vectors that trigger FAMMonitorDirectory failures.

## Package
lighttpd

## Files to modify
- src/network.c
- lighttpd-1.4.31.orig/src/network.c

## Target Source Code

### src/network.c

#### region() [lines 739-748]
```c
			);
		}

		if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
```

## Upstream Fix
```diff
origin: http://redmine.lighttpd.net/projects/lighttpd/repository/revisions/2925/diff/

Index: lighttpd-1.4.31/src/network.c
===================================================================
--- lighttpd-1.4.31.orig/src/network.c	2013-11-14 10:44:56.000000000 +0100
+++ lighttpd-1.4.31/src/network.c	2013-11-14 10:52:56.211535856 +0100
@@ -743,6 +743,14 @@
 			return -1;
 		}

+		/* completely useless identifier; required for client cert verification to work with sessions */
+		if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:",
+				"failed to set session context",
+				ERR_error_string(ERR_get_error(), NULL));
+			return -1;
+		}
+
 		SSL_CTX_set_options(s->ssl_ctx, ssloptions);
 		SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
```

Generate a backported patch for the SUSE target version.

[Assistant]
origin: http://redmine.lighttpd.net/projects/lighttpd/repository/revisions/2925/diff/

Index: lighttpd-1.4.31/src/network.c
===================================================================
--- lighttpd-1.4.31.orig/src/network.c	2013-11-14 10:44:56.000000000 +0100
+++ lighttpd-1.4.31/src/network.c	2013-11-14 10:52:56.211535856 +0100
@@ -743,6 +743,14 @@
 			return -1;
 		}

+		/* completely useless identifier; required for client cert verification to work with sessions */
+		if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:",
+				"failed to set session context",
+				ERR_error_string(ERR_get_error(), NULL));
+			return -1;
+		}
+
 		SSL_CTX_set_options(s->ssl_ctx, ssloptions);
 		SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2016-9556

The IsPixelGray function in MagickCore/pixel-accessor.h in ImageMagick 7.0.3-8 allows remote attackers to cause a denial of service (out-of-bounds heap read) via a crafted image file.

## Package
GraphicsMagick

## Files to modify
- GraphicsMagick-1.3.20.orig/coders/sun.c
- coders/sun.c

## Upstream Fix
```diff
Index: GraphicsMagick-1.3.20/coders/sun.c
===================================================================
--- GraphicsMagick-1.3.20.orig/coders/sun.c	2013-03-10 00:19:31.000000000 +0100
+++ GraphicsMagick-1.3.20/coders/sun.c	2016-10-03 15:26:07.822756467 +0200
@@ -1,5 +1,5 @@
 /*
-% Copyright (C) 2003 GraphicsMagick Group
+% Copyright (C) 2003-214 GraphicsMagick Group
 % Copyright (C) 2002 ImageMagick Studio
 % Copyright 1991-1999 E. I. du Pont de Nemours and Company
 %
@@ -39,6 +39,7 @@
 #include "magick/analyze.h"
 #include "magick/blob.h"
 #include "magick/colormap.h"
+#include "magick/log.h"
 #include "magick/magick.h"
 #include "magick/monitor.h"
 #include "magick/pixel_cache.h"
@@ -49,6 +50,63 @@
 */
 static unsigned int
   WriteSUNImage(const ImageInfo *,Image *);
+
+/* Raster Types */
+#define RT_STANDARD     1 /* Standard */
+#define RT_ENCODED      2 /* Byte encoded */
+#define RT_FORMAT_RGB   3 /* RGB format */
+
+/* Color Map Types */
+#define RMT_NONE        0 /* No color map */
+#define RMT_EQUAL_RGB   1 /* RGB color map */
+#define RMT_RAW         2 /* Raw color map */
+
+/*
+  Note that Sun headers described these fields as type 'int'.
+*/
+typedef struct _SUNInfo
+{
+  magick_uint32_t
+    magic,      /* Magick (identification) number */
+    width,      /* Width of image in pixels */
+    height,     /* Height of image in pixels */
+    depth,      /* Number of bits per pixel */
+    length,     /* Size of image data in bytes */
+    type,       /* Type of raster file */
+    maptype,    /* Type of color map */
+    maplength;  /* Size of the color map in bytes */
+} SUNInfo;
+
+static void LogSUNInfo(const SUNInfo *sun_info)
+{
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                        "SunHeader:\n"
+                        "    Magic:     0x%04X\n"
+                        "    Width:     %u\n"
+                        "    Height:    %u\n"
+                        "    Depth:     %u\n"
+                        "    Length:    %u\n"
+                        "    Type:      %u (%s)\n"
+                        "    MapType:   %u (%s)\n"
+                        "    MapLength: %u\n",
+                        sun_info->magic,
+                        sun_info->width,
+                        sun_info->height,
+                        sun_info->depth,
+                        sun_info->length,
+                        sun_info->type,
+                        (sun_info->type == RT_STANDARD ? "Standard (RT_STANDARD)" :
+                         (sun_info->type == RT_ENCODED ? "RLE encoded (RT_ENCODED)" :
+                          (sun_info->type == RT_FORMAT_RGB ? "RGB format (RT_FORMAT_RGB)" :
+                           "?"))),
+                        sun_info->maptype,
+                        (sun_info->maptype == RMT_NONE ? "No color map (RMT_NONE)" :
+                         (sun_info->maptype == RMT_EQUAL_RGB ? "RGB color map (RMT_EQUAL_RGB)" :
+                          (sun_info->maptype == RMT_RAW ? "Raw color map (RMT_RAW)" :
+                           "?"))),
+                        sun_info->maplength
+                        );
+}

 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -115,23 +173,28 @@ static unsigned int IsSUN(const unsigned
 %    o compressed_pixels:  The address of a byte (8 bits) array of compressed
 %      pixel data.
 %
-%    o length:  An integer value that is the total number of bytes of the
-%      source image (as just read by ReadBlob)
+%    o compressed_size:  An integer value that is the total number of bytes
+%      of the source image (as just read by ReadBlob)
 %
 %    o pixels:  The address of a byte (8 bits) array of pixel data created by
 %      the uncompression process.  The number of bytes in this array
 %      must be at least equal to the number columns times the number of rows
 %      of the source pixels.
 %
+%    o pixels_size: Decompressed pixels buffer size.
+%
 %
 */
-static unsigned int DecodeImage(const unsigned char *compressed_pixels,
-  const size_t length,unsigned char *pixels)
+static MagickPassFail
+DecodeImage(const unsigned char *compressed_pixels,
+            const size_t compressed_size,
+            unsigned char *pixels,
+            const size_t pixels_size)
 {
   register const unsigned char
     *p;

-  register long
+  register int
     count;

   register unsigned char
@@ -144,7 +207,8 @@ static unsigned int DecodeImage(const un
   assert(pixels != (unsigned char *) NULL);
   p=compressed_pixels;
   q=pixels;
-  while ((size_t) (p-compressed_pixels) < length)
+  while (((size_t) (p-compressed_pixels) < compressed_size) &&
+         ((size_t) (q-pixels) < pixels_size))
   {
     byte=(*p++);
     if (byte != 128U)
@@ -157,14 +221,14 @@ static unsigned int DecodeImage(const un
         count=(*p++);
         if (count > 0)
           byte=(*p++);
-        while (count >= 0)
+        while ((count >= 0) && ((size_t) (q-pixels) < pixels_size))
         {
           *q++=byte;
           count--;
         }
      }
   }
-  return(True);
+  return (((size_t) (q-pixels) == pixels_size) ? MagickTrue : MagickFalse);
 }

 /*
@@ -200,26 +264,6 @@ static unsigned int DecodeImage(const un
 */
 static Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
-#define RMT_EQUAL_RGB  1
-#define RMT_NONE  0
-#define RMT_RAW  2
-#define RT_STANDARD  1
-#define RT_ENCODED  2
-#define RT_FORMAT_RGB  3
-
-  typedef struct _SUNInfo
-  {
-    magick_uint32_t
-      magic,
-      width,
-      height,
-      depth,
-      length,
-      type,
-      maptype,
-      maplength;
-  } SUNInfo;
-
   Image
     *image;

@@ -245,7 +289,10 @@ static Image *ReadSUNImage(const ImageIn
     *p;

   size_t
-    count;
+    bytes_per_image,
+    bytes_per_line,
+    count,
+    sun_data_length;

   SUNInfo
     sun_info;
@@ -257,9 +304,6 @@ static Image *ReadSUNImage(const ImageIn
   unsigned int
     status;

-  unsigned long
-    bytes_per_line;
-
   /*
     Open image file.
   */
@@ -290,10 +334,46 @@ static Image *ReadSUNImage(const ImageIn
     sun_info.type=ReadBlobMSBLong(image);
     sun_info.maptype=ReadBlobMSBLong(image);
     sun_info.maplength=ReadBlobMSBLong(image);
+    LogSUNInfo(&sun_info);
+    if (EOFBlob(image))
+      ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+    /*
+      Verify that header values are in positive numeric range of a
+      32-bit 'int' even though we store them in an unsigned value.
+    */
+    if ((sun_info.magic | sun_info.width | sun_info.height | sun_info.depth |
+         sun_info.type | sun_info.maptype | sun_info.maplength) & (1U << 31))
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+    /*
+      Verify that we support the image sub-type
+    */
+    if ((sun_info.type != RT_STANDARD) &&
+        (sun_info.type != RT_ENCODED) &&
+        (sun_info.type != RT_FORMAT_RGB))
+      ThrowReaderException(CoderError,DataEncodingSchemeIsNotSupported,image);
+    /*
+      Verify that we support the colormap type
+    */
+    if ((sun_info.maptype != RMT_NONE) &&
+        (sun_info.maptype != RMT_EQUAL_RGB) &&
+        (sun_info.maptype != RMT_RAW))
+      ThrowReaderException(CoderError,ColormapTypeNotSupported,image);
+    /*
+      Insist that map length is zero if there is no colormap.
+    */
+    if ((sun_info.maptype == RMT_NONE) && (sun_info.maplength != 0))
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+    /*
+      Insist on a supported depth
+    */
+    if ((sun_info.depth != 1) &&
+        (sun_info.depth != 8) &&
+        (sun_info.depth != 24) &&
+        (sun_info.depth != 32))
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+
     image->columns= sun_info.width;
     image->rows= sun_info.height;
-    if (sun_info.depth == 0 || sun_info.depth > 32)
-      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
     image->depth
... (truncated)
```

Generate a backported patch for the SUSE target version.

[Assistant]
Index: GraphicsMagick-1.3.20/coders/sun.c
===================================================================
--- GraphicsMagick-1.3.20.orig/coders/sun.c	2013-03-10 00:19:31.000000000 +0100
+++ GraphicsMagick-1.3.20/coders/sun.c	2016-10-03 15:26:07.822756467 +0200
@@ -1,5 +1,5 @@
 /*
-% Copyright (C) 2003 GraphicsMagick Group
+% Copyright (C) 2003-214 GraphicsMagick Group
 % Copyright (C) 2002 ImageMagick Studio
 % Copyright 1991-1999 E. I. du Pont de Nemours and Company
 %
@@ -39,6 +39,7 @@
 #include "magick/analyze.h"
 #include "magick/blob.h"
 #include "magick/colormap.h"
+#include "magick/log.h"
 #include "magick/magick.h"
 #include "magick/monitor.h"
 #include "magick/pixel_cache.h"
@@ -49,6 +50,63 @@
 */
 static unsigned int
   WriteSUNImage(const ImageInfo *,Image *);
+
+/* Raster Types */
+#define RT_STANDARD     1 /* Standard */
+#define RT_ENCODED      2 /* Byte encoded */
+#define RT_FORMAT_RGB   3 /* RGB format */
+
+/* Color Map Types */
+#define RMT_NONE        0 /* No color map */
+#define RMT_EQUAL_RGB   1 /* RGB color map */
+#define RMT_RAW         2 /* Raw color map */
+
+/*
+  Note that Sun headers described these fields as type 'int'.
+*/
+typedef struct _SUNInfo
+{
+  magick_uint32_t
+    magic,      /* Magick (identification) number */
+    width,      /* Width of image in pixels */
+    height,     /* Height of image in pixels */
+    depth,      /* Number of bits per pixel */
+    length,     /* Size of image data in bytes */
+    type,       /* Type of raster file */
+    maptype,    /* Type of color map */
+    maplength;  /* Size of the color map in bytes */
+} SUNInfo;
+
+static void LogSUNInfo(const SUNInfo *sun_info)
+{
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                        "SunHeader:\n"
+                        "    Magic:     0x%04X\n"
+                        "    Width:     %u\n"
+                        "    Height:    %u\n"
+                        "    Depth:     %u\n"
+                        "    Length:    %u\n"
+                        "    Type:      %u (%s)\n"
+                        "    MapType:   %u (%s)\n"
+                        "    MapLength: %u\n",
+                        sun_info->magic,
+                        sun_info->width,
+                        sun_info->height,
+                        sun_info->depth,
+                        sun_info->length,
+                        sun_info->type,
+                        (sun_info->type == RT_STANDARD ? "Standard (RT_STANDARD)" :
+                         (sun_info->type == RT_ENCODED ? "RLE encoded (RT_ENCODED)" :
+                          (sun_info->type == RT_FORMAT_RGB ? "RGB format (RT_FORMAT_RGB)" :
+                           "?"))),
+                        sun_info->maptype,
+                        (sun_info->maptype == RMT_NONE ? "No color map (RMT_NONE)" :
+                         (sun_info->maptype == RMT_EQUAL_RGB ? "RGB color map (RMT_EQUAL_RGB)" :
+                          (sun_info->maptype == RMT_RAW ? "Raw color map (RMT_RAW)" :
+                           "?"))),
+                        sun_info->maplength
+                        );
+}

 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -115,23 +173,28 @@ static unsigned int IsSUN(const unsigned
 %    o compressed_pixels:  The address of a byte (8 bits) array of compressed
 %      pixel data.
 %
-%    o length:  An integer value that is the total number of bytes of the
-%      source image (as just read by ReadBlob)
+%    o compressed_size:  An integer value that is the total number of bytes
+%      of the source image (as just read by ReadBlob)
 %
 %    o pixels:  The address of a byte (8 bits) array of pixel data created by
 %      the uncompression process.  The number of bytes in this array
 %      must be at least equal to the number columns times the number of rows
 %      of the source pixels.
 %
+%    o pixels_size: Decompressed pixels buffer size.
+%
 %
 */
-static unsigned int DecodeImage(const unsigned char *compressed_pixels,
-  const size_t length,unsigned char *pixels)
+static MagickPassFail
+DecodeImage(const unsigned char *compressed_pixels,
+            const size_t compressed_size,
+            unsigned char *pixels,
+            const size_t pixels_size)
 {
   register const unsigned char
     *p;

-  register long
+  register int
     count;

   register unsigned char
@@ -144,7 +207,8 @@ static unsigned int DecodeImage(const un
   assert(pixels != (unsigned char *) NULL);
   p=compressed_pixels;
   q=pixels;
-  while ((size_t) (p-compressed_pixels) < length)
+  while (((size_t) (p-compressed_pixels) < compressed_size) &&
+         ((size_t) (q-pixels) < pixels_size))
   {
     byte=(*p++);
     if (byte != 128U)
@@ -157,14 +221,14 @@ static unsigned int DecodeImage(const un
         count=(*p++);
         if (count > 0)
           byte=(*p++);
-        while (count >= 0)
+        while ((count >= 0) && ((size_t) (q-pixels) < pixels_size))
         {
           *q++=byte;
           count--;
         }
      }
   }
-  return(True);
+  return (((size_t) (q-pixels) == pixels_size) ? MagickTrue : MagickFalse);
 }

 /*
@@ -200,26 +264,6 @@ static unsigned int DecodeImage(const un
 */
 static Image *ReadSUNImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
-#define RMT_EQUAL_RGB  1
-#define RMT_NONE  0
-#define RMT_RAW  2
-#define RT_STANDARD  1
-#define RT_ENCODED  2
-#define RT_FORMAT_RGB  3
-
-  typedef struct _SUNInfo
-  {
-    magick_uint32_t
-      magic,
-      width,
-      height,
-      depth,
-      length,
-      type,
-      maptype,
-      maplength;
-  } SUNInfo;
-
   Image
     *image;

@@ -245,7 +289,10 @@ static Image *ReadSUNImage(const ImageIn
     *p;

   size_t
-    count;
+    bytes_per_image,
+    bytes_per_line,
+    count,
+    sun_data_length;

   SUNInfo
     sun_info;
@@ -257,9 +304,6 @@ static Image *ReadSUNImage(const ImageIn
   unsigned int
     status;

-  unsigned long
-    bytes_per_line;
-
   /*
     Open image file.
   */
@@ -290,10 +334,46 @@ static Image *ReadSUNImage(const ImageIn
     sun_info.type=ReadBlobMSBLong(image);
     sun_info.maptype=ReadBlobMSBLong(image);
     sun_info.maplength=ReadBlobMSBLong(image);
+    LogSUNInfo(&sun_info);
+    if (EOFBlob(image))
+      ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+    /*
+      Verify that header values are in positive numeric range of a
+      32-bit 'int' even though we store them in an unsigned value.
+    */
+    if ((sun_info.magic | sun_info.width | sun_info.height | sun_info.depth |
+         sun_info.type | sun_info.maptype | sun_info.maplength) & (1U << 31))
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+    /*
+      Verify that we support the image sub-type
+    */
+    if ((sun_info.type != RT_STANDARD) &&
+        (sun_info.type != RT_ENCODED) &&
+        (sun_info.type != RT_FORMAT_RGB))
+      ThrowReaderException(CoderError,DataEncodingSchemeIsNotSupported,image);
+    /*
+      Verify that we support the colormap type
+    */
+    if ((sun_info.maptype != RMT_NONE) &&
+        (sun_info.maptype != RMT_EQUAL_RGB) &&
+        (sun_info.maptype != RMT_RAW))
+      ThrowReaderException(CoderError,ColormapTypeNotSupported,image);
+    /*
+      Insist that map length is zero if there is no colormap.
+    */
+    if ((sun_info.maptype == RMT_NONE) && (sun_info.maplength != 0))
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+    /*
+      Insist on a supported depth
+    */
+    if ((sun_info.depth != 1) &&
+        (sun_info.depth != 8) &&
+        (sun_info.depth != 24) &&
+        (sun_info.depth != 32))
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+
     image->columns= sun_info.width;
     image->rows= sun_info.height;
-    if (sun_info.depth == 0 || sun_info.depth > 32)
-      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
     image->depth=sun_info.depth <= 8 ? 8 : QuantumDepth;
     if (sun_info.depth < 24)
       {
@@ -304,6 +384,7 @@ static Image *ReadSUNImage(const ImageIn
         if (sun_info.maptype == RMT_EQUAL_RGB)
           image->colors=sun_info.maplength/3;
       }
+
     switch (sun_info.maptype)
     {
       case RMT_NONE:
@@ -333,17 +414,38 @@ static Image *ReadSUNImage(const ImageIn
         sun_colormap=MagickAllocateMemory(unsigned char *,image->colors);
         if (sun_colormap == (unsigned char *) NULL)
           ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
-            image);
-        (void) ReadBlob(image,image->colors,(char *) sun_colormap);
-        for (i=0; i < (long) image->colors; i++)
-          image->colormap[i].red=ScaleCharToQuantum(sun_colormap[i]);
-        (void) ReadBlob(image,image->colors,(char *) sun_colormap);
-        for (i=0; i < (long) image->colors; i++)
-          image->colormap[i].green=ScaleCharToQuantum(sun_colormap[i]);
-        (void) ReadBlob(image,image->colors,(char *) sun_colormap);
-        for (i=0; i < (long) image->colors; i++)
-          image->colormap[i].blue=ScaleCharToQuantum(sun_colormap[i]);
+                               image);
+        do
+          {
+            if (ReadBlob(image,image->colors,(char *) sun_colormap) !=
+                image->colors)
+              {
+                status = MagickFail;
+                break;
+              }
+            for (i=0; i < (long) image->colors; i++)
+              image->colormap[i].red=ScaleCharToQuantum(sun_colormap[i]);
+            if (ReadBlob(image,image->colors,(char *) sun_colormap) !=
+                image->colors)
+              {
+                status = MagickFail;
+                break;
+              }
+            for (i=0; i < (long) image->colors; i++)
+              image->colormap[i].green=ScaleCharToQuantum(sun_colormap[i]);
+            if (ReadBlob(image,image->colors,(char *) sun_colormap) !=
+                image->colors)
+              {
+                status = MagickFail;
+                break;
+              }
+            for (i=0; i < (long) image->colors; i++)
+              image->colormap[i].blue=ScaleCharToQuantum(sun_colormap[i]);
+            break;
+          } while (1);
         MagickFreeMemory(sun_colormap);
+        if (MagickFail == status)
+          ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
         break;
       }
       case RMT_RAW:
@@ -358,8 +460,12 @@ static Image *ReadSUNImage(const ImageIn
         if (sun_colormap == (unsigned char *) NULL)
           ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
             image);
-        (void) ReadBlob(image,sun_info.maplength,(char *) sun_colormap);
+        if (ReadBlob(image,sun_info.maplength,(char *) sun_colormap) !=
+            sun_info.maplength)
+          status = MagickFail;
         MagickFreeMemory(sun_colormap);
+        if (MagickFail == status)
+          ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
         break;
       }
       default:
@@ -371,41 +477,75 @@ static Image *ReadSUNImage(const ImageIn
     image->depth=8;
     if (sun_info.depth < 8)
       image->depth=sun_info.depth;
+
+    /*
+      Compute bytes per line and bytes per image for an unencoded
+      image.
+
+      "The width of a scan line is always 16-bits, padded when necessary."
+    */
+    bytes_per_line=MagickArraySize(sun_info.width,sun_info.depth)/8;
+    if ((bytes_per_line != 0) && (sun_info.depth == 1))
+      bytes_per_line += sun_info.width % 8 ? 1 : 0;
+    if (bytes_per_line != 0)
+      bytes_per_line=RoundUpToAlignment(bytes_per_line,2);
+
+    bytes_per_image=MagickArraySize(sun_info.height,bytes_per_line);
+
+    if (bytes_per_line == 0)
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+
+    if (bytes_per_image == 0)
+      ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+
+    if ((sun_info.type == RT_STANDARD) || (sun_info.type == RT_FORMAT_RGB))
+      if (bytes_per_image > sun_info.length)
+        ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+
     if (image_info->ping)
       {
         CloseBlob(image);
         return(image);
       }
-    sun_data=MagickAllocateMemory(unsigned char *,(size_t) sun_info.length);
+    if (sun_info.type == RT_ENCODED)
+      sun_data_length=(size_t) sun_info.length;
+    else
+      sun_data_length=bytes_per_image;
+    sun_data=MagickAllocateMemory(unsigned char *,sun_data_length);
     if (sun_data == (unsigned char *) NULL)
       ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
-    count=ReadBlob(image,sun_info.length,(char *) sun_data);
-    if ((count == 0) && (sun_info.type != RT_ENCODED))
-      ThrowReaderException(CorruptImageError,UnableToReadImageData,image);
+    if ((count=ReadBlob(image,sun_data_length,(char *) sun_data))
+        != sun_data_length)
+      {
+        MagickFreeMemory(sun_data);
+        ThrowReaderException(CorruptImageError,UnableToReadImageData,image);
+      }
     sun_pixels=sun_data;
-    bytes_per_line=0;
     if (sun_info.type == RT_ENCODED)
       {
-        unsigned long
-          height;
-
         /*
-          Read run-length encoded raster pixels.
+          Read run-length encoded raster pixels (padded to 16-bit boundary).
         */
-        height=sun_info.height;
-        bytes_per_line=2*(sun_info.width*sun_info.depth+15)/16;
-        sun_pixels=MagickAllocateMemory(unsigned char *,bytes_per_line*height);
+        sun_pixels=MagickAllocateMemory(unsigned char *,bytes_per_image);
         if (sun_pixels == (unsigned char *) NULL)
           ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
             image);
-        (void) DecodeImage(sun_data,sun_info.length,sun_pixels);
+        status &= DecodeImage(sun_data,sun_data_length,sun_pixels,bytes_per_image);
         MagickFreeMemory(sun_data);
+        if (status != MagickPass)
+          {
+            MagickFreeMemory(sun_pixels);
+            ThrowReaderException(CorruptImageError,UnableToRunlengthDecodeImage,image);
+          }
       }
     /*
       Convert SUN raster image to pixel packets.
     */
     p=sun_pixels;
     if (sun_info.depth == 1)
+      /*
+        Bilevel
+      */
       for (y=0; y < (long) image->rows; y++)
       {
         q=SetImagePixels(image,0,y,image->columns,1);
@@ -438,10 +578,9 @@ static Image *ReadSUNImage(const ImageIn
     else
       if (image->storage_class == PseudoClass)
         {
-	  unsigned long n = image->rows*(image->columns+image->columns%2);
-	  if ((sun_info.type == RT_ENCODED && n > bytes_per_line*image->rows) ||
-	      (sun_info.type != RT_ENCODED && n > sun_info.length))
-	    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+          /*
+            Colormapped
+          */
           for (y=0; y < (long) image->rows; y++)
           {
             q=SetImagePixels(image,0,y,image->columns,1);
@@ -464,11 +603,9 @@ static Image *ReadSUNImage(const ImageIn
 	}
       else
         {
-	  unsigned long n = image->columns*((image->matte) ? 4 : 3);
-	  n = image->rows*(n+image->columns%2);
-	  if ((sun_info.type == RT_ENCODED && n > bytes_per_line*image->rows) ||
-	      (sun_info.type != RT_ENCODED && n > sun_info.length))
-	    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+          /*
+            (A)BGR or (A)RGB
+          */
           for (y=0; y < (long) image->rows; y++)
           {
             q=SetImagePixels(image,0,y,image->columns,1);
@@ -650,25 +787,6 @@ ModuleExport void UnregisterSUNImage(voi
 */
 static unsigned int WriteSUNImage(const ImageInfo *image_info,Image *image)
 {
-#define RMT_EQUAL_RGB  1
-#define RMT_NONE  0
-#define RMT_RAW  2
-#define RT_STANDARD  1
-#define RT_FORMAT_RGB  3
-
-  typedef struct _SUNInfo
-  {
-    magick_uint32_t
-      magic,
-      width,
-      height,
-      depth,
-      length,
-      type,
-      maptype,
-      maplength;
-  } SUNInfo;
-
   long
     y;

@@ -769,6 +887,7 @@ static unsigned int WriteSUNImage(const
     /*
       Write SUN header.
     */
+    LogSUNInfo(&sun_info);
     (void) WriteBlobMSBLong(image,sun_info.magic);
     (void) WriteBlobMSBLong(image,sun_info.width);
     (void) WriteBlobMSBLong(image,sun_info.height);


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2016-6250

Integer overflow in the ISO9660 writer in libarchive before 3.2.1 allows remote attackers to cause a denial of service (application crash) or execute arbitrary code via vectors related to verifying filename lengths when writing an ISO9660 archive, which trigger a buffer overflow.

## Package
libarchive

## Files to modify
- libarchive-3.1.2.orig/libarchive/archive_read_support_format_mtree.c
- libarchive/archive_read_support_format_mtree.c
- libarchive/test/test_read_format_mtree_crash747.c

## Target Source Code

### Makefile.am

#### region() [lines 375-461]
```c
	libarchive/test/test_read_format_ar.c			\
	libarchive/test/test_read_format_cab.c			\
	libarchive/test/test_read_format_cab_filename.c		\
	libarchive/test/test_read_format_cpio_afio.c		\
	libarchive/test/test_read_format_cpio_bin.c		\
	libarchive/test/test_read_format_cpio_bin_Z.c		\
	libarchive/test/test_read_format_cpio_bin_be.c		\
	libarchive/test/test_read_format_cpio_bin_bz2.c		\
	libarchive/test/test_read_format_cpio_bin_gz.c		\
	libarchive/test/test_read_format_cpio_bin_lzip.c	\
	libarchive/test/test_read_format_cpio_bin_lzma.c	\
	libarchive/test/test_read_format_cpio_bin_xz.c		\
	libarchive/test/test_read_format_cpio_filename.c	\
	libarchive/test/test_read_format_cpio_odc.c		\
	libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c	\
	libarchive/test/test_read_format_cpio_svr4_gzip.c	\
	libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c	\
	libarchive/test/test_read_format_cpio_svr4c_Z.c		\
	libarchive/test/test_read_format_empty.c		\
	libarchive/test/test_read_format_gtar_filename.c	\
	libarchive/test/test_read_format_gtar_gz.c		\
	libarchive/test/test_read_format_gtar_lzma.c		\
	libarchive/test/test_read_format_gtar_sparse.c		\
	libarchive/test/test_read_format_iso_Z.c		\
	libarchive/test/test_read_format_iso_multi_extent.c	\
	libarchive/test/test_read_format_iso_xorriso.c		\
	libarchive/test/test_read_format_isojoliet_bz2.c	\
	libarchive/test/test_read_format_isojoliet_long.c	\
	libarchive/test/test_read_format_isojoliet_rr.c		\
	libarchive/test/test_read_format_isojoliet_versioned.c	\
	libarchive/test/test_read_format_isorr_bz2.c		\
	libarchive/test/test_read_format_isorr_ce.c		\
	libarchive/test/test_read_format_isorr_new_bz2.c	\
	libarchive/test/test_read_format_isorr_rr_moved.c	\
	libarchive/test/test_read_format_isozisofs_bz2.c	\
	libarchive/test/test_read_format_lha.c			\
	libarchive/test/test_read_format_lha_filename.c		\
	libarchive/test/test_read_format_mtree.c		\
	libarchive/test/test_read_format_pax_bz2.c		\
	libarchive/test/test_read_format_rar.c			\
	libarchive/test/test_read_format_raw.c			\
	libarchive/test/test_read_format_tar.c			\
	libarchive/test/test_read_format_tar_empty_filename.c	\
	libarchive/test/test_read_format_tar_filename.c		\
	libarchive/test/test_read_format_tbz.c			\
	libarchive/test/test_read_format_tgz.c			\
	libarchive/test/test_read_format_tlz.c			\
	libarchive/test/test_read_format_txz.c			\
	libarchive/test/test_read_format_tz.c			\
	libarchive/test/test_read_format_ustar_filename.c	\
	libarchive/test/test_read_form
/* ... truncated ... */
```

### libarchive/archive_read_support_format_mtree.c

#### get_line_size() [lines 240-276]
```c
}

static ssize_t
get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
{
	ssize_t len;

	len = 0;
	while (len < avail) {
		switch (*b) {
		case '\0':/* Non-ascii character or control character. */
			if (nlsize != NULL)
				*nlsize = 0;
			return (-1);
		case '\r':
			if (avail-len > 1 && b[1] == '\n') {
				if (nlsize != NULL)
					*nlsize = 2;
				return (len+2);
			}
			/* FALL THROUGH */
		case '\n':
			if (nlsize != NULL)
				*nlsize = 1;
			return (len+1);
		default:
			b++;
			len++;
			break;
		}
	}
	if (nlsize != NULL)
		*nlsize = 0;
	return (avail);
}

static ssize_t
```

#### next_line() [lines 274-321]
```c
}

static ssize_t
next_line(struct archive_read *a,
    const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
{
	ssize_t len;
	int quit;

	quit = 0;
	if (*avail == 0) {
		*nl = 0;
		len = 0;
	} else
		len = get_line_size(*b, *avail, nl);
	/*
	 * Read bytes more while it does not reach the end of line.
	 */
	while (*nl == 0 && len == *avail && !quit) {
		ssize_t diff = *ravail - *avail;
		size_t nbytes_req = (*ravail+1023) & ~1023U;
		ssize_t tested;

		/* Increase reading bytes if it is not enough to at least
		 * new two lines. */
		if (nbytes_req < (size_t)*ravail + 160)
			nbytes_req <<= 1;

		*b = __archive_read_ahead(a, nbytes_req, avail);
		if (*b == NULL) {
			if (*ravail >= *avail)
				return (0);
			/* Reading bytes reaches the end of file. */
			*b = __archive_read_ahead(a, *avail, avail);
			quit = 1;
		}
		*ravail = *avail;
		*b += diff;
		*avail -= diff;
		tested = len;/* Skip some bytes we already determinated. */
		len = get_line_size(*b, *avail, nl);
		if (len >= 0)
			len += tested;
	}
	return (len);
}

/*
```

### libarchive/test/CMakeLists.txt

#### IF() [lines 87-173]
```c
    test_read_filter_program_signature.c
    test_read_filter_uudecode.c
    test_read_format_7zip.c
    test_read_format_ar.c
    test_read_format_cab.c
    test_read_format_cab_filename.c
    test_read_format_cpio_afio.c
    test_read_format_cpio_bin.c
    test_read_format_cpio_bin_Z.c
    test_read_format_cpio_bin_be.c
    test_read_format_cpio_bin_bz2.c
    test_read_format_cpio_bin_gz.c
    test_read_format_cpio_bin_lzip.c
    test_read_format_cpio_bin_lzma.c
    test_read_format_cpio_bin_xz.c
    test_read_format_cpio_filename.c
    test_read_format_cpio_odc.c
    test_read_format_cpio_svr4_bzip2_rpm.c
    test_read_format_cpio_svr4_gzip.c
    test_read_format_cpio_svr4_gzip_rpm.c
    test_read_format_cpio_svr4c_Z.c
    test_read_format_empty.c
    test_read_format_gtar_filename.c
    test_read_format_gtar_gz.c
    test_read_format_gtar_lzma.c
    test_read_format_gtar_sparse.c
    test_read_format_iso_Z.c
    test_read_format_iso_multi_extent.c
    test_read_format_iso_xorriso.c
    test_read_format_isojoliet_bz2.c
    test_read_format_isojoliet_long.c
    test_read_format_isojoliet_rr.c
    test_read_format_isojoliet_versioned.c
    test_read_format_isorr_bz2.c
    test_read_format_isorr_ce.c
    test_read_format_isorr_new_bz2.c
    test_read_format_isorr_rr_moved.c
    test_read_format_isozisofs_bz2.c
    test_read_format_lha.c
    test_read_format_lha_filename.c
    test_read_format_mtree.c
    test_read_format_pax_bz2.c
    test_read_format_rar.c
    test_read_format_raw.c
    test_read_format_tar.c
    test_read_format_tar_empty_filename.c
    test_read_format_tar_filename.c
    test_read_format_tbz.c
    test_read_format_tgz.c
    test_read_format_tlz.c
    test_read_format_txz.c
    test_read_format_tz.c
    test_read_format_ustar_filename.c
    test_read_format_xar.c
    test_read_format_zip.c
    test_read_format_zip_comment_stored.c
    test_read_format_zip_filename.c
    test_read_format_zip_mac_metadata.c
    test_read_format_zip_sfx.c
    test_read_large.c
    test_read_pax_truncated.c
    test_read_position.c
    test_read_set_format.c
    test_read_truncated.c
    test_read_truncated_filter.c
    test_sparse_basic.c
    test_tar_filenames.c
    test_tar_large.c
    test_ustar_filenames.c
    test_ustar_filename_encoding.c
    test_write_disk.c
    test_write_disk_appledouble.c
    test_write_disk_failures.c
    test_write_disk_hardlink.c
    test_write_disk_hfs_compression.c
    test_write_disk_lookup.c
    test_write_disk_mac_metadata.c
    test_wri
/* ... truncated ... */
```

### Type definitions

```c
/* from archive_private.h */
struct archive {
	/*
	 * The magic/state values are used to sanity-check the
	 * client's usage.  If an API function is called at a
	 * ridiculous time, or the client passes us an invalid
	 * pointer, these values allow me to catch that.
	 */
	unsigned int	magic;
	unsigned int	state;

	/*
	 * Some public API functions depend on the "real" type of the
	 * archive object.
	 */
	struct archive_vtable *vtable;

	int		  archive_format;
	const char	 *archive_format_name;

	int	  compression_code;	/* Currently active compression. */
	const char *compression_name;

	/* Number of file entries processed. */
	int		  file_count;

	int		  archive_error_number;
	const char	 *error;
	struct archive_string	error_string;

	char *current_code;
	unsigned current_codepage; /* Current ACP(ANSI CodePage). */
	unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */
	struct archive_string_conv *sconv;
};
```

## Upstream Fix
```diff
commit eec077f52bfa2d3f7103b4b74d52572ba8a15aca
Author: Tim Kientzle <kientzle@acm.org>
Date:   Sun Sep 18 17:27:47 2016 -0700

    Issue 747 (and others?):  Avoid OOB read when parsing multiple long lines

    The mtree bidder needs to look several lines ahead
    in the input.  It does this by extending the read-ahead
    and parsing subsequent lines from the same growing buffer.
    A bookkeeping error when extending the read-ahead would
    sometimes lead it to significantly over-count the
    size of the line being read.

Index: libarchive-3.1.2/Makefile.am
===================================================================
--- libarchive-3.1.2.orig/Makefile.am
+++ libarchive-3.1.2/Makefile.am
@@ -414,6 +414,7 @@ libarchive_test_SOURCES=					\
 	libarchive/test/test_read_format_lha.c			\
 	libarchive/test/test_read_format_lha_filename.c		\
 	libarchive/test/test_read_format_mtree.c		\
+	libarchive/test/test_read_format_mtree_crash747.c	\
 	libarchive/test/test_read_format_pax_bz2.c		\
 	libarchive/test/test_read_format_rar.c			\
 	libarchive/test/test_read_format_rar_invalid1.c		\
Index: libarchive-3.1.2/libarchive/archive_read_support_format_mtree.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read_support_format_mtree.c
+++ libarchive-3.1.2/libarchive/archive_read_support_format_mtree.c
@@ -277,6 +277,15 @@ get_line_size(const char *b, ssize_t ava
 	return (avail);
 }

+/*
+ *  <---------------- ravail --------------------->
+ *  <-- diff ------> <---  avail ----------------->
+ *                   <---- len ----------->
+ * | Previous lines | line being parsed  nl extra |
+ *                  ^
+ *                  b
+ *
+ */
 static ssize_t
 next_line(struct archive_read *a,
     const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
@@ -315,7 +324,7 @@ next_line(struct archive_read *a,
 		*b += diff;
 		*avail -= diff;
 		tested = len;/* Skip some bytes we already determinated. */
-		len = get_line_size(*b, *avail, nl);
+		len = get_line_size(*b + len, *avail - len, nl);
 		if (len >= 0)
 			len += tested;
 	}
Index: libarchive-3.1.2/libarchive/test/CMakeLists.txt
===================================================================
--- libarchive-3.1.2.orig/libarchive/test/CMakeLists.txt
+++ libarchive-3.1.2/libarchive/test/CMakeLists.txt
@@ -126,6 +126,7 @@ IF(ENABLE_TEST)
     test_read_format_lha.c
     test_read_format_lha_filename.c
     test_read_format_mtree.c
+    test_read_format_mtree_crash747.c
     test_read_format_pax_bz2.c
     test_read_format_rar.c
     test_read_format_raw.c
Index: libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.c
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2003-2016 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+
+/*
+ * Reproduce the crash reported in Github Issue #747.
+ */
+DEFINE_TEST(test_read_format_mtree_crash747)
+{
+	const char *reffile = "test_read_format_mtree_crash747.mtree.bz2";
+	struct archive *a;
+
+	extract_reference_file(reffile);
+
+	assert((a = archive_read_new()) != NULL);
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_bzip2(a));
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_mtree(a));
+	assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_filename(a, reffile, 10240));
+	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
Index: libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu
@@ -0,0 +1,6 @@
+begin 600 test_read_format_mtree_crash747.mtree.bz2
+M0EIH.3%!62936:OH@(@``'/[@,`0`@!``'^
```

Generate a backported patch for the SUSE target version.

[Assistant]
commit eec077f52bfa2d3f7103b4b74d52572ba8a15aca
Author: Tim Kientzle <kientzle@acm.org>
Date:   Sun Sep 18 17:27:47 2016 -0700

    Issue 747 (and others?):  Avoid OOB read when parsing multiple long lines

    The mtree bidder needs to look several lines ahead
    in the input.  It does this by extending the read-ahead
    and parsing subsequent lines from the same growing buffer.
    A bookkeeping error when extending the read-ahead would
    sometimes lead it to significantly over-count the
    size of the line being read.

Index: libarchive-3.1.2/Makefile.am
===================================================================
--- libarchive-3.1.2.orig/Makefile.am
+++ libarchive-3.1.2/Makefile.am
@@ -414,6 +414,7 @@ libarchive_test_SOURCES=					\
 	libarchive/test/test_read_format_lha.c			\
 	libarchive/test/test_read_format_lha_filename.c		\
 	libarchive/test/test_read_format_mtree.c		\
+	libarchive/test/test_read_format_mtree_crash747.c	\
 	libarchive/test/test_read_format_pax_bz2.c		\
 	libarchive/test/test_read_format_rar.c			\
 	libarchive/test/test_read_format_rar_invalid1.c		\
Index: libarchive-3.1.2/libarchive/archive_read_support_format_mtree.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read_support_format_mtree.c
+++ libarchive-3.1.2/libarchive/archive_read_support_format_mtree.c
@@ -277,6 +277,15 @@ get_line_size(const char *b, ssize_t ava
 	return (avail);
 }

+/*
+ *  <---------------- ravail --------------------->
+ *  <-- diff ------> <---  avail ----------------->
+ *                   <---- len ----------->
+ * | Previous lines | line being parsed  nl extra |
+ *                  ^
+ *                  b
+ *
+ */
 static ssize_t
 next_line(struct archive_read *a,
     const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
@@ -315,7 +324,7 @@ next_line(struct archive_read *a,
 		*b += diff;
 		*avail -= diff;
 		tested = len;/* Skip some bytes we already determinated. */
-		len = get_line_size(*b, *avail, nl);
+		len = get_line_size(*b + len, *avail - len, nl);
 		if (len >= 0)
 			len += tested;
 	}
Index: libarchive-3.1.2/libarchive/test/CMakeLists.txt
===================================================================
--- libarchive-3.1.2.orig/libarchive/test/CMakeLists.txt
+++ libarchive-3.1.2/libarchive/test/CMakeLists.txt
@@ -126,6 +126,7 @@ IF(ENABLE_TEST)
     test_read_format_lha.c
     test_read_format_lha_filename.c
     test_read_format_mtree.c
+    test_read_format_mtree_crash747.c
     test_read_format_pax_bz2.c
     test_read_format_rar.c
     test_read_format_raw.c
Index: libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.c
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2003-2016 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+
+/*
+ * Reproduce the crash reported in Github Issue #747.
+ */
+DEFINE_TEST(test_read_format_mtree_crash747)
+{
+	const char *reffile = "test_read_format_mtree_crash747.mtree.bz2";
+	struct archive *a;
+
+	extract_reference_file(reffile);
+
+	assert((a = archive_read_new()) != NULL);
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_bzip2(a));
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_mtree(a));
+	assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_filename(a, reffile, 10240));
+	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
Index: libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu
@@ -0,0 +1,6 @@
+begin 600 test_read_format_mtree_crash747.mtree.bz2
+M0EIH.3%!62936:OH@(@``'/[@,`0`@!``'^```)A@9\`$`@@`'4)049!IIH!
+MM021-0,F@&@6````9%>$(K!GIC*XFR0`$```J0+:$XP```!D-F)H[#SE9+2'
+4+E"L=ASXUI%R(I"HD'ZA(5?1`Q``
+`
+end


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2013-4560

Use-after-free vulnerability in lighttpd before 1.4.33 allows remote attackers to cause a denial of service (segmentation fault and crash) via unspecified vectors that trigger FAMMonitorDirectory failures.

## Package
lighttpd

## Files to modify
- src/request.c

## Upstream Fix
```diff
From 162bb2fe51552c43192799d4514c4d8b0de3265b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20B=C3=BChler?= <stbuehler@web.de>
Date: Sat, 17 Nov 2012 11:54:18 +0100
Subject: [PATCH] Fix DoS in header value split (reported by Jesse Sipprell)

---
 src/request.c |   75 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 38 insertions(+), 37 deletions(-)

diff --git a/src/request.c b/src/request.c
index de1a782..0d749e6 100644
--- a/src/request.c
+++ b/src/request.c
@@ -209,9 +209,11 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) {
 #endif

 static int http_request_split_value(array *vals, buffer *b) {
-	char *s;
 	size_t i;
 	int state = 0;
+
+	const char *current;
+	const char *token_start = NULL, *token_end = NULL;
 	/*
 	 * parse
 	 *
@@ -222,53 +224,52 @@ static int http_request_split_value(array *vals, buffer *b) {

 	if (b->used == 0) return 0;

-	s = b->ptr;
-
-	for (i =0; i < b->used - 1; ) {
-		char *start = NULL, *end = NULL;
+	current = b->ptr;
+	for (i =  0; i < b->used; ++i, ++current) {
 		data_string *ds;

 		switch (state) {
-		case 0: /* ws */
-
-			/* skip ws */
-			for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
-
-
-			state = 1;
-			break;
-		case 1: /* value */
-			start = s;
-
-			for (; *s != ',' && i < b->used - 1; i++, s++);
-			if (start == s) break; /* empty fields are skipped */
-			end = s - 1;
-
-			for (; end > start && (*end == ' ' || *end == '\t'); end--);
-			if (start == end) break; /* empty fields are skipped */
-
-			if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
-				ds = data_string_init();
+		case 0: /* find start of a token */
+			switch (*current) {
+			case ' ':
+			case '\t': /* skip white space */
+			case ',': /* skip empty token */
+				break;
+			case '\0': /* end of string */
+				return 0;
+			default:
+				/* found real data, switch to state 1 to find the end of the token */
+				token_start = token_end = current;
+				state = 1;
+				break;
 			}
+			break;
+		case 1: /* find end of token and last non white space character */
+			switch (*current) {
+			case ' ':
+			case '\t':
+				/* space - don't update token_end */
+				break;
+			case ',':
+			case '\0': /* end of string also marks the end of a token */
+				if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
+					ds = data_string_init();
+				}

-			buffer_copy_string_len(ds->value, start, end-start+1);
-			array_insert_unique(vals, (data_unset *)ds);
+				buffer_copy_string_len(ds->value, token_start, token_end-token_start+1);
+				array_insert_unique(vals, (data_unset *)ds);

-			if (*s == ',') {
 				state = 0;
-				i++;
-				s++;
-			} else {
-				/* end of string */
-
-				state = 2;
+				break;
+			default:
+				/* no white space, update token_end to include current character */
+				token_end = current;
+				break;
 			}
 			break;
-		default:
-			i++;
-			break;
 		}
 	}
+
 	return 0;
 }

--
1.7.10.4
```

Generate a backported patch for the SUSE target version.

[Assistant]
From 162bb2fe51552c43192799d4514c4d8b0de3265b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20B=C3=BChler?= <stbuehler@web.de>
Date: Sat, 17 Nov 2012 11:54:18 +0100
Subject: [PATCH] Fix DoS in header value split (reported by Jesse Sipprell)

---
 src/request.c |   75 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 38 insertions(+), 37 deletions(-)

diff --git a/src/request.c b/src/request.c
index de1a782..0d749e6 100644
--- a/src/request.c
+++ b/src/request.c
@@ -209,9 +209,11 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) {
 #endif

 static int http_request_split_value(array *vals, buffer *b) {
-	char *s;
 	size_t i;
 	int state = 0;
+
+	const char *current;
+	const char *token_start = NULL, *token_end = NULL;
 	/*
 	 * parse
 	 *
@@ -222,53 +224,52 @@ static int http_request_split_value(array *vals, buffer *b) {

 	if (b->used == 0) return 0;

-	s = b->ptr;
-
-	for (i =0; i < b->used - 1; ) {
-		char *start = NULL, *end = NULL;
+	current = b->ptr;
+	for (i =  0; i < b->used; ++i, ++current) {
 		data_string *ds;

 		switch (state) {
-		case 0: /* ws */
-
-			/* skip ws */
-			for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
-
-
-			state = 1;
-			break;
-		case 1: /* value */
-			start = s;
-
-			for (; *s != ',' && i < b->used - 1; i++, s++);
-			if (start == s) break; /* empty fields are skipped */
-			end = s - 1;
-
-			for (; end > start && (*end == ' ' || *end == '\t'); end--);
-			if (start == end) break; /* empty fields are skipped */
-
-			if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
-				ds = data_string_init();
+		case 0: /* find start of a token */
+			switch (*current) {
+			case ' ':
+			case '\t': /* skip white space */
+			case ',': /* skip empty token */
+				break;
+			case '\0': /* end of string */
+				return 0;
+			default:
+				/* found real data, switch to state 1 to find the end of the token */
+				token_start = token_end = current;
+				state = 1;
+				break;
 			}
+			break;
+		case 1: /* find end of token and last non white space character */
+			switch (*current) {
+			case ' ':
+			case '\t':
+				/* space - don't update token_end */
+				break;
+			case ',':
+			case '\0': /* end of string also marks the end of a token */
+				if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
+					ds = data_string_init();
+				}

-			buffer_copy_string_len(ds->value, start, end-start+1);
-			array_insert_unique(vals, (data_unset *)ds);
+				buffer_copy_string_len(ds->value, token_start, token_end-token_start+1);
+				array_insert_unique(vals, (data_unset *)ds);

-			if (*s == ',') {
 				state = 0;
-				i++;
-				s++;
-			} else {
-				/* end of string */
-
-				state = 2;
+				break;
+			default:
+				/* no white space, update token_end to include current character */
+				token_end = current;
+				break;
 			}
 			break;
-		default:
-			i++;
-			break;
 		}
 	}
+
 	return 0;
 }

--
1.7.10.4