[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
- coders/meta.c
- GraphicsMagick-1.3.21.orig/coders/meta.c

## Upstream Fix
```diff
ff -r 4f748e625c82 -r 8da95e3e5e81 coders/meta.c
Index: GraphicsMagick-1.3.21/coders/meta.c
===================================================================
--- GraphicsMagick-1.3.21.orig/coders/meta.c	2015-02-28 21:51:58.000000000 +0100
@@ -129,14 +129,16 @@ static unsigned int IsMETA(const unsigne

 typedef struct _html_code
 {
-  short
+  unsigned short
     len;
+
   const char
     *code,
     val;
+
 } html_code;

-static html_code html_codes[] = {
+static html_code const html_codes[] = {
 #ifdef HANDLE_GT_LT
   { 4,"<",'<' },
   { 4,">",'>' },
@@ -179,29 +181,36 @@ static int stringnicmp(const char *p,con
   return(toupper((int) *p)-toupper((int) *q));
 }

-static int convertHTMLcodes(char *s, int len)
+static size_t convertHTMLcodes(char *s, const size_t len)
 {
-  if (len <=0 || s==(char*)NULL || *s=='\0')
+  int val;
+
+  if ((len == 0) || (s == (char*) NULL) || (*s=='\0'))
     return 0;

-  if (s[1] == '#')
-    {
-      int val, o;
+  /*
+    Check for hex or decimal character escape.

-      if (sscanf(s,"&#%d;",&val) == 1)
-      {
-        o = 3;
-        while (s[o] != ';')
+    e.g. hex: " ", decimal " "
+
+    Note that scanf is expected to parse the number in hex or decimal
+    and that it does not require the terminating ';' to appear in
+    order to parse the numeric argument.
+  */
+  if ((len > 3) && (s[1] == '#') && (strchr(s,';') != (char *) NULL) &&
+      (sscanf(s,"&#%d;",&val) == 1))
+    {
+      size_t o = 3;
+      while (s[o] != ';')
         {
           o++;
           if (o > 5)
             break;
         }
-        if (o < 6)
-          (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
-        *s = val;
-        return o;
-      }
+      if (o < 6)
+        (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
+      *s = val;
+      return o;
     }
   else
     {
@@ -281,10 +290,10 @@ static long parse8BIM(Image *ifile, Imag
   char
     brkused,
     quoted,
-    *line,
-    *token,
-    *newstr,
-    *name;
+    *line = (char *) NULL,
+    *token = (char *) NULL,
+    *newstr = (char *) NULL,
+    *name = (char *) NULL;

   int
     state,
@@ -299,7 +308,7 @@ static long parse8BIM(Image *ifile, Imag
   size_t
     inputlen = BUFFER_SZ;

-  long
+  ssize_t
     savedolen = 0L,
     outputlen = 0L;

@@ -313,7 +322,8 @@ static long parse8BIM(Image *ifile, Imag
   dataset = 0;
   recnum = 0;
   line = MagickAllocateMemory(char *,inputlen);
-  name = token = (char *)NULL;
+  if (line == (char *) NULL)
+    goto parse8BIM_failure;
   savedpos = 0;
   while(super_fgets(&line,&inputlen,ifile)!=NULL)
   {
@@ -321,7 +331,11 @@ static long parse8BIM(Image *ifile, Imag
     next=0;

     token = MagickAllocateMemory(char *,inputlen);
+    if (token == (char *) NULL)
+      goto parse8BIM_failure;
     newstr = MagickAllocateMemory(char *,inputlen);
+    if (newstr == (char *) NULL)
+      goto parse8BIM_failure;
     while (Tokenizer(&token_info, 0, token, inputlen, line,
           (char *) "", (char *) "=",
       (char *) "\"", 0, &brkused,&next,&quoted)==0)
@@ -354,8 +368,9 @@ static long parse8BIM(Image *ifile, Imag
                 break;
               case 2:
                 name = MagickAllocateMemory(char *,strlen(newstr)+1);
-                if (name)
-                  (void) strcpy(name,newstr);
+                if (name == (char *) NULL)
+                  goto parse8BIM_failure;
+                (void) strcpy(name,newstr);
                 break;
             }
             state++;
@@ -367,7 +382,7 @@ static long parse8BIM(Image *ifile, Imag
             int
               next;

-            unsigned long
+            size_t
               len;

             char
@@ -384,7 +399,7 @@ static long parse8BIM(Image *ifile, Imag
                   char
                     *s = &token[next-1];

-                  len -= convertHTMLcodes(s, (int) strlen(s));
+                  len -= convertHTMLcodes(s, strlen(s));
                 }
             }

@@ -400,6 +415,8 @@ static long parse8BIM(Image *ifile, Imag
                   {
                     long diff = outputlen - savedolen;
                     currentpos = TellBlob(ofile);
+                    if (currentpos < 0)
+                      goto parse8BIM_failure;
                     (void) SeekBlob(ofile,savedpos,SEEK_SET);
                     (void) WriteBlobMSBLong(ofile,diff);
                     (void) SeekBlob(ofile,currentpos,SEEK_SET);
@@ -433,7 +450,7 @@ static long parse8BIM(Image *ifile, Imag
                     next=0;
                     outputlen += len;
                     while (len--)
-                      (void) WriteBlobByte(ofile,token[next++]);
+                      (void) WriteBlobByte(ofile,token[next++]); /* boom */

                     if (outputlen & 1)
                       {
@@ -445,6 +462,8 @@ static long parse8BIM(Image *ifile, Imag
                   {
                     /* patch in a fake length for now and fix it later */
                     savedpos = TellBlob(ofile);
+                    if (savedpos < 0)
+                      goto parse8BIM_failure;
                     (void) WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
                     outputlen += 4;
                     savedolen = outputlen;
@@ -478,12 +497,22 @@ static long parse8BIM(Image *ifile, Imag
       long diff = outputlen - savedolen;

       currentpos = TellBlob(ofile);
+      if (currentpos < 0)
+        goto parse8BIM_failure;
+
       (void) SeekBlob(ofile,savedpos,SEEK_SET);
       (void) WriteBlobMSBLong(ofile,diff);
       (void) SeekBlob(ofile,currentpos,SEEK_SET);
       savedolen = 0L;
     }
   return outputlen;
+
+ parse8BIM_failure:
+  MagickFreeMemory(token);
+  MagickFreeMemory(newstr);
+  MagickFreeMemory(name);
+  MagickFreeMemory(line);
+  return 0L;
 }

 static char *super_fgets_w(char **b, size_t *blen, Image *file)
@@ -542,10 +571,10 @@ static long parse8BIMW(Image *ifile, Ima
   char
     brkused,
     quoted,
-    *line,
-    *token,
-    *newstr,
-    *name;
+    *line = (char *) NULL,
+    *token = (char *) NULL,
+    *newstr = (char *) NULL,
+    *name = (char *) NULL;

   int
     state,
@@ -560,7 +589,7 @@ static long parse8BIMW(Image *ifile, Ima
   size_t
     inputlen = BUFFER_SZ;

-  long
+  ssize_t
     savedolen = 0L,
     outputlen = 0L;

@@ -574,6 +603,8 @@ static long parse8BIMW(Image *ifile, Ima
   dataset = 0;
   recnum = 0;
   line = MagickAllocateMemory(char *,inputlen);
+  if (line == (char *) NULL)
+    goto parse8BIMW_failure;
   name = token = (char *)NULL;
   savedpos = 0;
   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -586,7 +617,11 @@ static long parse8BIMW(Image *ifile, Ima
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "META CODER Parse8BIM: %s (%lu)",line, (unsigned long) inputlen);
     token = MagickAllocateMemory(char *,inputlen);
+    if (token == (char *) NULL)
+      goto parse8BIMW_failure;
     newstr = MagickAllocateMemory(char *,inputlen);
+    if (newstr == (char *) NULL)
+      goto parse8BIMW_failure;
     while (Tokenizer(&token_info, 0, token, inputlen, line,
           (char *) "", (char *) "=",
       (char *) "\"", 0, &brkused,&next,&quoted)==0)
@@ -619,8 +654,9 @@ static long parse8BIMW(Image *ifile, Ima
                 break;
               case 2:
                 name = MagickAllocateMemory(char *,strlen(newstr)+1);
-                if (name)
-                  (void) strcpy(name,newstr);
+                if (name == (char *) NULL)
+                  goto parse8BIMW_failure;
+                (void) strcpy(name,newstr);
                 break;
             }
             state++;
@@ -632,7 +668,7 @@ static long parse8BIMW(Image *ifile, Ima
             int
               next;

-            unsigned long
+            size_t
               len;

             char
@@ -649,7 +685,7 @@ static long parse8BIMW(Image *ifile, Ima
                   char
                     *s = &token[next-1];

-
... (truncated)
```

Generate a backported patch for the SUSE target version.

[Assistant]
ff -r 4f748e625c82 -r 8da95e3e5e81 coders/meta.c
Index: GraphicsMagick-1.3.21/coders/meta.c
===================================================================
--- GraphicsMagick-1.3.21.orig/coders/meta.c	2015-02-28 21:51:58.000000000 +0100
@@ -129,14 +129,16 @@ static unsigned int IsMETA(const unsigne

 typedef struct _html_code
 {
-  short
+  unsigned short
     len;
+
   const char
     *code,
     val;
+
 } html_code;

-static html_code html_codes[] = {
+static html_code const html_codes[] = {
 #ifdef HANDLE_GT_LT
   { 4,"<",'<' },
   { 4,">",'>' },
@@ -179,29 +181,36 @@ static int stringnicmp(const char *p,con
   return(toupper((int) *p)-toupper((int) *q));
 }

-static int convertHTMLcodes(char *s, int len)
+static size_t convertHTMLcodes(char *s, const size_t len)
 {
-  if (len <=0 || s==(char*)NULL || *s=='\0')
+  int val;
+
+  if ((len == 0) || (s == (char*) NULL) || (*s=='\0'))
     return 0;

-  if (s[1] == '#')
-    {
-      int val, o;
+  /*
+    Check for hex or decimal character escape.

-      if (sscanf(s,"&#%d;",&val) == 1)
-      {
-        o = 3;
-        while (s[o] != ';')
+    e.g. hex: " ", decimal " "
+
+    Note that scanf is expected to parse the number in hex or decimal
+    and that it does not require the terminating ';' to appear in
+    order to parse the numeric argument.
+  */
+  if ((len > 3) && (s[1] == '#') && (strchr(s,';') != (char *) NULL) &&
+      (sscanf(s,"&#%d;",&val) == 1))
+    {
+      size_t o = 3;
+      while (s[o] != ';')
         {
           o++;
           if (o > 5)
             break;
         }
-        if (o < 6)
-          (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
-        *s = val;
-        return o;
-      }
+      if (o < 6)
+        (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
+      *s = val;
+      return o;
     }
   else
     {
@@ -281,10 +290,10 @@ static long parse8BIM(Image *ifile, Imag
   char
     brkused,
     quoted,
-    *line,
-    *token,
-    *newstr,
-    *name;
+    *line = (char *) NULL,
+    *token = (char *) NULL,
+    *newstr = (char *) NULL,
+    *name = (char *) NULL;

   int
     state,
@@ -299,7 +308,7 @@ static long parse8BIM(Image *ifile, Imag
   size_t
     inputlen = BUFFER_SZ;

-  long
+  ssize_t
     savedolen = 0L,
     outputlen = 0L;

@@ -313,7 +322,8 @@ static long parse8BIM(Image *ifile, Imag
   dataset = 0;
   recnum = 0;
   line = MagickAllocateMemory(char *,inputlen);
-  name = token = (char *)NULL;
+  if (line == (char *) NULL)
+    goto parse8BIM_failure;
   savedpos = 0;
   while(super_fgets(&line,&inputlen,ifile)!=NULL)
   {
@@ -321,7 +331,11 @@ static long parse8BIM(Image *ifile, Imag
     next=0;

     token = MagickAllocateMemory(char *,inputlen);
+    if (token == (char *) NULL)
+      goto parse8BIM_failure;
     newstr = MagickAllocateMemory(char *,inputlen);
+    if (newstr == (char *) NULL)
+      goto parse8BIM_failure;
     while (Tokenizer(&token_info, 0, token, inputlen, line,
           (char *) "", (char *) "=",
       (char *) "\"", 0, &brkused,&next,&quoted)==0)
@@ -354,8 +368,9 @@ static long parse8BIM(Image *ifile, Imag
                 break;
               case 2:
                 name = MagickAllocateMemory(char *,strlen(newstr)+1);
-                if (name)
-                  (void) strcpy(name,newstr);
+                if (name == (char *) NULL)
+                  goto parse8BIM_failure;
+                (void) strcpy(name,newstr);
                 break;
             }
             state++;
@@ -367,7 +382,7 @@ static long parse8BIM(Image *ifile, Imag
             int
               next;

-            unsigned long
+            size_t
               len;

             char
@@ -384,7 +399,7 @@ static long parse8BIM(Image *ifile, Imag
                   char
                     *s = &token[next-1];

-                  len -= convertHTMLcodes(s, (int) strlen(s));
+                  len -= convertHTMLcodes(s, strlen(s));
                 }
             }

@@ -400,6 +415,8 @@ static long parse8BIM(Image *ifile, Imag
                   {
                     long diff = outputlen - savedolen;
                     currentpos = TellBlob(ofile);
+                    if (currentpos < 0)
+                      goto parse8BIM_failure;
                     (void) SeekBlob(ofile,savedpos,SEEK_SET);
                     (void) WriteBlobMSBLong(ofile,diff);
                     (void) SeekBlob(ofile,currentpos,SEEK_SET);
@@ -433,7 +450,7 @@ static long parse8BIM(Image *ifile, Imag
                     next=0;
                     outputlen += len;
                     while (len--)
-                      (void) WriteBlobByte(ofile,token[next++]);
+                      (void) WriteBlobByte(ofile,token[next++]); /* boom */

                     if (outputlen & 1)
                       {
@@ -445,6 +462,8 @@ static long parse8BIM(Image *ifile, Imag
                   {
                     /* patch in a fake length for now and fix it later */
                     savedpos = TellBlob(ofile);
+                    if (savedpos < 0)
+                      goto parse8BIM_failure;
                     (void) WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
                     outputlen += 4;
                     savedolen = outputlen;
@@ -478,12 +497,22 @@ static long parse8BIM(Image *ifile, Imag
       long diff = outputlen - savedolen;

       currentpos = TellBlob(ofile);
+      if (currentpos < 0)
+        goto parse8BIM_failure;
+
       (void) SeekBlob(ofile,savedpos,SEEK_SET);
       (void) WriteBlobMSBLong(ofile,diff);
       (void) SeekBlob(ofile,currentpos,SEEK_SET);
       savedolen = 0L;
     }
   return outputlen;
+
+ parse8BIM_failure:
+  MagickFreeMemory(token);
+  MagickFreeMemory(newstr);
+  MagickFreeMemory(name);
+  MagickFreeMemory(line);
+  return 0L;
 }

 static char *super_fgets_w(char **b, size_t *blen, Image *file)
@@ -542,10 +571,10 @@ static long parse8BIMW(Image *ifile, Ima
   char
     brkused,
     quoted,
-    *line,
-    *token,
-    *newstr,
-    *name;
+    *line = (char *) NULL,
+    *token = (char *) NULL,
+    *newstr = (char *) NULL,
+    *name = (char *) NULL;

   int
     state,
@@ -560,7 +589,7 @@ static long parse8BIMW(Image *ifile, Ima
   size_t
     inputlen = BUFFER_SZ;

-  long
+  ssize_t
     savedolen = 0L,
     outputlen = 0L;

@@ -574,6 +603,8 @@ static long parse8BIMW(Image *ifile, Ima
   dataset = 0;
   recnum = 0;
   line = MagickAllocateMemory(char *,inputlen);
+  if (line == (char *) NULL)
+    goto parse8BIMW_failure;
   name = token = (char *)NULL;
   savedpos = 0;
   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -586,7 +617,11 @@ static long parse8BIMW(Image *ifile, Ima
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                           "META CODER Parse8BIM: %s (%lu)",line, (unsigned long) inputlen);
     token = MagickAllocateMemory(char *,inputlen);
+    if (token == (char *) NULL)
+      goto parse8BIMW_failure;
     newstr = MagickAllocateMemory(char *,inputlen);
+    if (newstr == (char *) NULL)
+      goto parse8BIMW_failure;
     while (Tokenizer(&token_info, 0, token, inputlen, line,
           (char *) "", (char *) "=",
       (char *) "\"", 0, &brkused,&next,&quoted)==0)
@@ -619,8 +654,9 @@ static long parse8BIMW(Image *ifile, Ima
                 break;
               case 2:
                 name = MagickAllocateMemory(char *,strlen(newstr)+1);
-                if (name)
-                  (void) strcpy(name,newstr);
+                if (name == (char *) NULL)
+                  goto parse8BIMW_failure;
+                (void) strcpy(name,newstr);
                 break;
             }
             state++;
@@ -632,7 +668,7 @@ static long parse8BIMW(Image *ifile, Ima
             int
               next;

-            unsigned long
+            size_t
               len;

             char
@@ -649,7 +685,7 @@ static long parse8BIMW(Image *ifile, Ima
                   char
                     *s = &token[next-1];

-                  len -= convertHTMLcodes(s, (int) strlen(s));
+                  len -= convertHTMLcodes(s, strlen(s));
                 }
             }

@@ -665,6 +701,8 @@ static long parse8BIMW(Image *ifile, Ima
                   {
                     long diff = outputlen - savedolen;
                     currentpos = TellBlob(ofile);
+                    if (currentpos < 0)
+                      goto parse8BIMW_failure;
                     (void) SeekBlob(ofile,savedpos,SEEK_SET);
                     (void) WriteBlobMSBLong(ofile,diff);
                     (void) SeekBlob(ofile,currentpos,SEEK_SET);
@@ -710,6 +748,8 @@ static long parse8BIMW(Image *ifile, Ima
                   {
                     /* patch in a fake length for now and fix it later */
                     savedpos = TellBlob(ofile);
+                    if (savedpos < 0)
+                      goto parse8BIMW_failure;
                     (void) WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
                     outputlen += 4;
                     savedolen = outputlen;
@@ -743,12 +783,21 @@ static long parse8BIMW(Image *ifile, Ima
       long diff = outputlen - savedolen;

       currentpos = TellBlob(ofile);
+      if (currentpos < 0)
+        goto parse8BIMW_failure;
       (void) SeekBlob(ofile,savedpos,SEEK_SET);
       (void) WriteBlobMSBLong(ofile,diff);
       (void) SeekBlob(ofile,currentpos,SEEK_SET);
       savedolen = 0L;
     }
   return outputlen;
+
+ parse8BIMW_failure:
+  MagickFreeMemory(token);
+  MagickFreeMemory(newstr);
+  MagickFreeMemory(name);
+  MagickFreeMemory(line);
+  return 0L;
 }

 /* some defines for the different JPEG block types */
@@ -835,11 +884,12 @@ static int jpeg_skip_variable(Image *ifi
   return 0;
 }

-static int jpeg_skip_variable2(Image *ifile, Image *ARGUNUSED(ofile))
+static int jpeg_skip_variable2(Image *ifile, Image *ofile)
 {
   unsigned int  length;
   int c1,c2;

+  ARG_NOT_USED(ofile);
   if ((c1 = ReadBlobByte(ifile)) == EOF) return M_EOI;
   if ((c2 = ReadBlobByte(ifile)) == EOF) return M_EOI;

@@ -908,8 +958,6 @@ static int jpeg_skip_till_marker(Image *
 }
 #endif

-static char psheader[] = "\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0";
-
 /* Embed binary IPTC data into a JPEG image. */
 static int jpeg_embed(Image *ifile, Image *ofile, Image *iptc)
 {
@@ -952,9 +1000,12 @@ static int jpeg_embed(Image *ifile, Imag

         if (iptc != (Image *)NULL)
           {
+            static const char psheader_base[] = "\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0";
+            char psheader[sizeof(psheader_base)];
             len=GetBlobSize(iptc);
             if (len & 1)
               len++; /* make the length even */
+            (void) strlcpy(psheader,psheader_base,sizeof(psheader));
             psheader[ 2 ] = (len+16)>>8;
             psheader[ 3 ] = (len+16)&0xff;
             for (inx = 0; inx < 18; inx++)
@@ -1250,7 +1301,7 @@ static Image *ReadMETAImage(const ImageI

       DestroyImage(buff);
     }
-  if (LocaleCompare(image_info->magick,"IPTC") == 0)
+  if (LocaleNCompare(image_info->magick,"IPTC",4) == 0)
     {
       buff=AllocateImage((ImageInfo *) NULL);
       if (buff == (Image *) NULL)
@@ -1260,7 +1311,7 @@ static Image *ReadMETAImage(const ImageI
         {
           DestroyImage(buff);
           ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
-            image)
+                               image);
         }
       AttachBlob(buff->blob,blob,length);
       /* write out the header - length field patched below */
@@ -1286,14 +1337,21 @@ static Image *ReadMETAImage(const ImageI
         }

       /* subtract off the length of the 8BIM stuff */
+      blob=GetBlobStreamData(buff); /* blob may be realloced */
+      if ((blob == (const unsigned char *) NULL) || (GetBlobSize(buff) < 12))
+        {
+          DestroyImage(buff);
+          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
+                               image);
+        }
       length=GetBlobSize(buff)-12;
       blob[10]=(unsigned char) ((length >> 8) & 0xff);
       blob[11]=(unsigned char) (length & 0xff);
       blob=GetBlobStreamData(buff);
       length=GetBlobSize(buff);
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "Store IPTC profile, size %lu bytes",
-                            (unsigned long) length);
+                            "Store IPTC profile, size %" MAGICK_SIZE_T_F
+                            "u bytes",(MAGICK_SIZE_T) length);
       (void) SetImageProfile(image,"IPTC",blob,length);
       DetachBlob(buff->blob);
       MagickFreeMemory(blob)
@@ -1840,9 +1898,14 @@ static int formatIPTC(Image *ifile, Imag
     else
       {
         if (foundiptc)
-          return -1;
+          {
+            return -1;
+          }
         else
-          continue;
+          {
+            c = ReadBlobByte(ifile);
+            continue;
+          }
       }

     /* we found the 0x1c tag and now grab the dataset and record number tags */
@@ -1888,7 +1951,11 @@ static int formatIPTC(Image *ifile, Imag
     for (tagindx=0; tagindx<taglen; tagindx++)
     {
       c=ReadBlobByte(ifile);
-      if (c == EOF) return -1;
+      if (c == EOF)
+        {
+          MagickFreeMemory(str);
+          return -1;
+        }
       str[tagindx] = (unsigned char) c;
     }
     str[taglen] = 0;
@@ -2011,7 +2078,11 @@ static int formatIPTCfromBuffer(Image *o
     for (tagindx=0; tagindx<taglen; tagindx++)
     {
       c = *s++; len--;
-      if (len < 0) return -1;
+      if (len < 0)
+        {
+          MagickFreeMemory(str);
+          return -1;
+        }
       str[tagindx] = (unsigned char) c;
     }
     str[ taglen ] = 0;
@@ -2030,6 +2101,13 @@ static int formatIPTCfromBuffer(Image *o
   return tagsfound;
 }

+#define Format8BIMLiberate()                    \
+  do                                            \
+    {                                           \
+      MagickFreeMemory(PString);                \
+      MagickFreeMemory(str);                    \
+    } while(0);
+
 static int format8BIM(Image *ifile, Image *ofile)
 {
   char
@@ -2045,109 +2123,138 @@ static int format8BIM(Image *ifile, Imag
     c;

   unsigned char
-    *PString,
-    *str;
+    *PString=0,
+    *str=0;

   resCount = 0;

   c =ReadBlobByte(ifile);
   while (c != EOF)
-  {
-    if (c == '8')
-      {
-        unsigned char
-          buffer[5];
+    {
+      if (c == '8')
+        {
+          unsigned char
+            buffer[5];

-        buffer[0] = (unsigned char) c;
-        for (i=1; i<4; i++)
+          buffer[0] = (unsigned char) c;
+          for (i=1; i<4; i++)
+            {
+              c=ReadBlobByte(ifile);
+              if (c == EOF)
+                {
+                  Format8BIMLiberate();
+                  return -1;
+                }
+              buffer[i] = (unsigned char) c;
+            }
+          buffer[4] = 0;
+          if (strcmp((const char *)buffer, "8BIM") != 0)
+            continue;
+        }
+      else
         {
           c=ReadBlobByte(ifile);
-          if (c == EOF) return -1;
-          buffer[i] = (unsigned char) c;
-        }
-        buffer[4] = 0;
-        if (strcmp((const char *)buffer, "8BIM") != 0)
           continue;
-      }
-    else
-      {
-        c=ReadBlobByte(ifile);
-        continue;
-      }
-
-    /* we found the OSType (8BIM) and now grab the ID, PString, and Size fields */
-    ID = ReadBlobMSBShort(ifile);
-    if (ID < 0) return -1;
-    {
-      unsigned char
-        plen;
+        }

-      c=ReadBlobByte(ifile);
-      if (c == EOF) return -1;
-      plen = (unsigned char) c;
-      PString=MagickAllocateMemory(unsigned char *,(unsigned int) (plen+1));
-      if (PString == (unsigned char *) NULL)
-      {
-        (void) printf("MemoryAllocationFailed");
-        return 0;
-      }
-      for (i=0; i<plen; i++)
-      {
-        c=ReadBlobByte(ifile);
-        if (c == EOF) return -1;
-        PString[i] = (unsigned char) c;
-      }
-      PString[ plen ] = 0;
-      if (!(plen&1))
-      {
-        c=ReadBlobByte(ifile);
-        if (c == EOF) return -1;
-      }
-    }
-    Size = ReadBlobMSBLong(ifile);
-    if (Size < 0) return -1;
-    /* make a buffer to hold the data and snag it from the input stream */
-    str=MagickAllocateMemory(unsigned char *,(size_t) Size);
-    if (str == (unsigned char *) NULL)
+      /* we found the OSType (8BIM) and now grab the ID, PString, and Size fields */
+      ID = ReadBlobMSBShort(ifile);
+      if (ID < 0)
+        {
+          Format8BIMLiberate();
+          return -1;
+        }
       {
-        (void) printf("MemoryAllocationFailed");
-        return 0;
-      }
-    for (i=0; i<Size; i++)
-    {
-      c=ReadBlobByte(ifile);
-      if (c == EOF) return -1;
-      str[i] = (unsigned char) c;
-    }
+        unsigned char
+          plen;

-    /* we currently skip thumbnails, since it does not make
-     * any sense preserving them in a real world application
-     */
-    if (ID != THUMBNAIL_ID)
-      {
-        /* now finish up by formatting this binary data into
-         * ASCII equivalent
-         */
-        if (strlen((const char *) PString) != 0)
-          FormatString(temp, "8BIM#%d#%s=", ID, PString);
-        else
-          FormatString(temp, "8BIM#%d=", ID);
-        (void) WriteBlobString(ofile,temp);
-        if (ID == IPTC_ID)
+        c=ReadBlobByte(ifile);
+        if (c == EOF)
           {
-            formatString(ofile, "IPTC", 4);
-            (void) formatIPTCfromBuffer(ofile, (char *)str, (long) Size);
+            Format8BIMLiberate();
+            return -1;
+          }
+        plen = (unsigned char) c;
+        PString=MagickAllocateMemory(unsigned char *,(unsigned int) (plen+1));
+        if (PString == (unsigned char *) NULL)
+          {
+            (void) printf("MemoryAllocationFailed");
+            Format8BIMLiberate();
+            return 0;
+          }
+        for (i=0; i<plen; i++)
+          {
+            c=ReadBlobByte(ifile);
+            if (c == EOF)
+              {
+                Format8BIMLiberate();
+                return -1;
+              }
+            PString[i] = (unsigned char) c;
+          }
+        PString[ plen ] = 0;
+        if (!(plen&1))
+          {
+            c=ReadBlobByte(ifile);
+            if (c == EOF)
+              {
+                Format8BIMLiberate();
+                return -1;
+              }
           }
-        else
-          formatString(ofile, (char *)str, (long) Size);
       }
-    MagickFreeMemory(str);
-    MagickFreeMemory(PString);
+      Size = ReadBlobMSBLong(ifile);
+      if (Size < 0)
+        {
+          Format8BIMLiberate();
+          return -1;
+        }
+      /* make a buffer to hold the data and snag it from the input stream */
+      str=MagickAllocateMemory(unsigned char *,(size_t) Size);
+      if (str == (unsigned char *) NULL)
+        {
+          (void) printf("MemoryAllocationFailed");
+          Format8BIMLiberate();
+          return 0;
+        }
+      for (i=0; i<Size; i++)
+        {
+          c=ReadBlobByte(ifile);
+          if (c == EOF)
+            {
+              Format8BIMLiberate();
+              return -1;
+            }
+          str[i] = (unsigned char) c;
+        }
+
+      /* we currently skip thumbnails, since it does not make
+       * any sense preserving them in a real world application
+       */
+      if (ID != THUMBNAIL_ID)
+        {
+          /* now finish up by formatting this binary data into
+           * ASCII equivalent
+           */
+          if (strlen((const char *) PString) != 0)
+            FormatString(temp, "8BIM#%d#%s=", ID, PString);
+          else
+            FormatString(temp, "8BIM#%d=", ID);
+          (void) WriteBlobString(ofile,temp);
+          if (ID == IPTC_ID)
+            {
+              formatString(ofile, "IPTC", 4);
+              (void) formatIPTCfromBuffer(ofile, (char *)str, (long) Size);
+            }
+          else
+            formatString(ofile, (char *)str, (long) Size);
+        }
+      Format8BIMLiberate();

-    resCount++;
+      resCount++;

-    c=ReadBlobByte(ifile);
-  }
+      c=ReadBlobByte(ifile);
+    }
   return resCount;
 }


[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-2015-3197

ssl/s2_srvr.c in OpenSSL 1.0.1 before 1.0.1r and 1.0.2 before 1.0.2f does not prevent use of disabled ciphers, which makes it easier for man-in-the-middle attackers to defeat cryptographic protection mechanisms by performing computations on SSLv2 traffic, related to the get_client_master_key and get_client_hello functions.

## Package
openssl

## Files to modify
- openssl-1.0.1i.orig/crypto/rsa/rsa_ameth.c
- crypto/rsa/rsa_ameth.c
- openssl-1.0.1i/crypto/rsa/rsa_ameth.c

## Target Source Code

### crypto/rsa/rsa_ameth.c

#### region() [lines 248-335]
```c
		}
	ret=1;
err:
	if (m != NULL) OPENSSL_free(m);
	return(ret);
	}

static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
							ASN1_PCTX *ctx)
	{
	return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
	}

static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
							ASN1_PCTX *ctx)
	{
	return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
	}

static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
					X509_ALGOR **pmaskHash)
	{
	const unsigned char *p;
	int plen;
	RSA_PSS_PARAMS *pss;

	*pmaskHash = NULL;

	if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE)
		return NULL;
	p = alg->parameter->value.sequence->data;
	plen = alg->parameter->value.sequence->length;
	pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);

	if (!pss)
		return NULL;

	if (pss->maskGenAlgorithm)
		{
		ASN1_TYPE *param = pss->maskGenAlgorithm->parameter;
		if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) == NID_mgf1
			&& param->type == V_ASN1_SEQUENCE)
			{
			p = param->value.sequence->data;
			plen = param->value.sequence->length;
			*pmaskHash = d2i_X509_ALGOR(NULL, &p, plen);
			}
		}

	return pss;
	}

static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
				X509_ALGOR *maskHash, int indent)
	{
	int rv = 0;
	if (!pss)
		{
		if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0)
			return 0;
		return 1;
		}
	if (BIO_puts(bp, "\n") <= 0)
		goto err;
	if (!BIO_indent(bp, indent, 128))
		goto err;
	if (BIO_puts(bp, "Hash Algorithm: ") <= 0)
		goto err;

	if (pss->hashAlgorithm)
		{
		if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0)
			goto err;
		}
	else if (BIO_puts(bp, "sha1 (default)") <= 0)
		goto err;

	if (BIO_puts(bp, "\n") <= 0)
		goto err;

	if (!BIO_indent(bp, indent, 128))
		goto err;

	if (BIO_puts(bp, "Mask Algorithm: ") <= 0)
			goto err;
	if (pss->maskGenAlgorithm)
		{
```

## Upstream Fix
```diff
From d8541d7e9e63bf5f343af24644046c8d96498c17 Mon Sep 17 00:00:00 2001
From: "Dr. Stephen Henson" <steve@openssl.org>
Date: Fri, 2 Oct 2015 13:10:29 +0100
Subject: [PATCH] Add PSS parameter check.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Avoid seg fault by checking mgf1 parameter is not NULL. This can be
triggered during certificate verification so could be a DoS attack
against a client or a server enabling client authentication.

Thanks to Loïc Jonas Etienne (Qnective AG) for discovering this bug.

CVE-2015-3194

Reviewed-by: Matt Caswell <matt@openssl.org>
---
 crypto/rsa/rsa_ameth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 93e071de75e2a..c7f1148a1ded1 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -279,7 +279,7 @@ static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
     if (pss->maskGenAlgorithm) {
         ASN1_TYPE *param = pss->maskGenAlgorithm->parameter;
         if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) == NID_mgf1
-            && param->type == V_ASN1_SEQUENCE) {
+            && param && param->type == V_ASN1_SEQUENCE) {
             p = param->value.sequence->data;
             plen = param->value.sequence->length;
             *pmaskHash = d2i_X509_ALGOR(NULL, &p, plen);
```

Generate a backported patch for the SUSE target version.

[Assistant]
From d8541d7e9e63bf5f343af24644046c8d96498c17 Mon Sep 17 00:00:00 2001
From: "Dr. Stephen Henson" <steve@openssl.org>
Date: Fri, 2 Oct 2015 13:10:29 +0100
Subject: [PATCH] Add PSS parameter check.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Avoid seg fault by checking mgf1 parameter is not NULL. This can be
triggered during certificate verification so could be a DoS attack
against a client or a server enabling client authentication.

Thanks to Loïc Jonas Etienne (Qnective AG) for discovering this bug.

CVE-2015-3194

Reviewed-by: Matt Caswell <matt@openssl.org>
---
 crypto/rsa/rsa_ameth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: openssl-1.0.1i/crypto/rsa/rsa_ameth.c
===================================================================
--- openssl-1.0.1i.orig/crypto/rsa/rsa_ameth.c	2015-12-03 17:56:38.292632624 +0100
+++ openssl-1.0.1i/crypto/rsa/rsa_ameth.c	2015-12-03 17:58:11.106130819 +0100
@@ -287,7 +287,7 @@ static RSA_PSS_PARAMS *rsa_pss_decode(co
 		{
 		ASN1_TYPE *param = pss->maskGenAlgorithm->parameter;
 		if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) == NID_mgf1
-			&& param->type == V_ASN1_SEQUENCE)
+			&& param && param->type == V_ASN1_SEQUENCE)
 			{
 			p = param->value.sequence->data;
 			plen = param->value.sequence->length;


[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-4658

xpointer.c in libxml2 before 2.9.5 (as used in Apple iOS before 10, OS X before 10.12, tvOS before 10, and watchOS before 3, and other products) does not forbid namespace nodes in XPointer ranges, which allows remote attackers to execute arbitrary code or cause a denial of service (use-after-free and memory corruption) via a crafted XML document.

## Package
libxml2

## Files to modify
- xmlregexp.c

## Upstream Fix
```diff
From cbb271655cadeb8dbb258a64701d9a3a0c4835b4 Mon Sep 17 00:00:00 2001
From: Pranjal Jumde <pjumde@apple.com>
Date: Mon, 7 Mar 2016 06:34:26 -0800
Subject: [PATCH] Bug 757711: heap-buffer-overflow in xmlFAParsePosCharGroup
 <https://bugzilla.gnome.org/show_bug.cgi?id=757711>

* xmlregexp.c:
(xmlFAParseCharRange): Only advance to the next character if
there is no error.  Advancing to the next character in case of
an error while parsing regexp leads to an out of bounds access.
---
 xmlregexp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/xmlregexp.c b/xmlregexp.c
index 727fef4d70..ca3b4f46dc 100644
--- a/xmlregexp.c
+++ b/xmlregexp.c
@@ -5057,11 +5057,12 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) {
 	ERROR("Expecting the end of a char range");
 	return;
     }
-    NEXTL(len);
+
     /* TODO check that the values are acceptable character ranges for XML */
     if (end < start) {
 	ERROR("End of range is before start of range");
     } else {
+        NEXTL(len);
         xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
 		           XML_REGEXP_CHARVAL, start, end, NULL);
     }
```

Generate a backported patch for the SUSE target version.

[Assistant]
From cbb271655cadeb8dbb258a64701d9a3a0c4835b4 Mon Sep 17 00:00:00 2001
From: Pranjal Jumde <pjumde@apple.com>
Date: Mon, 7 Mar 2016 06:34:26 -0800
Subject: Bug 757711: heap-buffer-overflow in xmlFAParsePosCharGroup
 <https://bugzilla.gnome.org/show_bug.cgi?id=757711>

* xmlregexp.c:
(xmlFAParseCharRange): Only advance to the next character if
there is no error.  Advancing to the next character in case of
an error while parsing regexp leads to an out of bounds access.
---
 xmlregexp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/xmlregexp.c b/xmlregexp.c
index 727fef4..ca3b4f4 100644
--- a/xmlregexp.c
+++ b/xmlregexp.c
@@ -5057,11 +5057,12 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) {
 	ERROR("Expecting the end of a char range");
 	return;
     }
-    NEXTL(len);
+
     /* TODO check that the values are acceptable character ranges for XML */
     if (end < start) {
 	ERROR("End of range is before start of range");
     } else {
+        NEXTL(len);
         xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
 		           XML_REGEXP_CHARVAL, start, end, NULL);
     }
--
cgit v0.12


[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-2015-3197

ssl/s2_srvr.c in OpenSSL 1.0.1 before 1.0.1r and 1.0.2 before 1.0.2f does not prevent use of disabled ciphers, which makes it easier for man-in-the-middle attackers to defeat cryptographic protection mechanisms by performing computations on SSLv2 traffic, related to the get_client_master_key and get_client_hello functions.

## Package
openssl

## Files to modify
- openssl-1.0.1i/ssl/ssl_err.c
- openssl-1.0.1i.orig/ssl/ssl_locl.h
- openssl-1.0.1i.orig/ssl/ssl_sess.c
- openssl-1.0.1i.orig/ssl/s3_clnt.c
- openssl-1.0.1i/ssl/ssl_locl.h

## Target Source Code

### ssl/ssl.h

#### ERR_load_SSL_strings() [lines 2215-2301]
```c
#define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
#define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176
#define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT		 272
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179
#define SSL_F_SSL_DO_HANDSHAKE				 180
#define SSL_F_SSL_GET_NEW_SESSION			 181
#define SSL_F_SSL_GET_PREV_SESSION			 217
#define SSL_F_SSL_GET_SERVER_SEND_CERT			 182
#define SSL_F_SSL_GET_SERVER_SEND_PKEY			 317
#define SSL_F_SSL_GET_SIGN_PKEY				 183
#define SSL_F_SSL_INIT_WBIO_BUFFER			 184
#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185
#define SSL_F_SSL_NEW					 186
#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT	 300
#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT		 302
#define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT	 310
#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT	 301
#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT		 303
#define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT	 311
#define SSL_F_SSL_PEEK					 270
#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT		 281
#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT		 282
#define SSL_F_SSL_READ					 223
#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
#define SSL_F_SSL_SESSION_NEW				 189
#define SSL_F_SSL_SESSION_PRINT_FP			 190
#define SSL_F_SSL_SESSION_SET1_ID_CONTEXT		 312
#define SSL_F_SSL_SESS_CERT_NEW				 225
#define SSL_F_SSL_SET_CERT				 191
#define SSL_F_SSL_SET_CIPHER_LIST			 271
#define SSL_F_SSL_SET_FD				 192
#define SSL_F_SSL_SET_PKEY				 193
#define SSL_F_SSL_SET_PURPOSE				 227
#define SSL_F_SSL_SET_RFD				 194
#define SSL_F_SSL_SET_SESSION				 195
#define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
#define SSL_F_SSL_SET_SESSION_TICKET_EXT		 294
#define SSL_F_SSL_SET_TRUST				 228
#define SSL_F_SSL_SET_WFD				 196
#define SSL_F_SSL_SHUTDOWN				 224
#define SSL_F_SSL_SRP_CTX_INIT				 313
#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243
#define SSL_F_SSL_UNDEFINED_FUNCTION			 197
#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
#define SSL_F_SSL_USE_CERTIFICATE			 198
#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
#define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
#define SSL_F_SSL_USE_PRIVATEKEY			 201
#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203
#define SSL_F_SSL_USE_PSK_IDENTITY_HINT			 273
#define SSL_F_SSL_USE_RSAPRIVATEKEY			 204
#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205
#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
#define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
#define SSL_F_SSL_WRITE					 208
#define SSL_F_TLS1_CERT_VERIFY_MAC			 286
#define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT		 274
#define SSL_F_TLS1_ENC					 210
#define SSL_F_TLS1_EXPORT_KEYING_MATERIAL		 314
#define SSL_F_TLS1_HEARTBEAT				 315
#define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT		 275
#define SSL_F_TLS1_PR
/* ... truncated ... */
```

### ssl/s3_clnt.c

#### ssl3_get_new_session_ticket() [lines 2049-2141]
```c
	return(X509_NAME_cmp(*a,*b));
	}
#ifndef OPENSSL_NO_TLSEXT
int ssl3_get_new_session_ticket(SSL *s)
	{
	int ok,al,ret=0, ticklen;
	long n;
	const unsigned char *p;
	unsigned char *d;

	n=s->method->ssl_get_message(s,
		SSL3_ST_CR_SESSION_TICKET_A,
		SSL3_ST_CR_SESSION_TICKET_B,
		-1,
		16384,
		&ok);

	if (!ok)
		return((int)n);

	if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
		{
		s->s3->tmp.reuse_message=1;
		return(1);
		}
	if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
		{
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
		goto f_err;
		}
	if (n < 6)
		{
		/* need at least ticket_lifetime_hint + ticket length */
		al = SSL_AD_DECODE_ERROR;
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
		goto f_err;
		}

	p=d=(unsigned char *)s->init_msg;
	n2l(p, s->session->tlsext_tick_lifetime_hint);
	n2s(p, ticklen);
	/* ticket_lifetime_hint + ticket_length + ticket */
	if (ticklen + 6 != n)
		{
		al = SSL_AD_DECODE_ERROR;
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
		goto f_err;
		}
	if (s->session->tlsext_tick)
		{
		OPENSSL_free(s->session->tlsext_tick);
		s->session->tlsext_ticklen = 0;
		}
	s->session->tlsext_tick = OPENSSL_malloc(ticklen);
	if (!s->session->tlsext_tick)
		{
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	memcpy(s->session->tlsext_tick, p, ticklen);
	s->session->tlsext_ticklen = ticklen;
	/* There are two ways to detect a resumed ticket sesion.
	 * One is to set an appropriate session ID and then the server
	 * must return a match in ServerHello. This allows the normal
	 * client session ID matching to work and we know much
	 * earlier that the ticket has been accepted.
	 *
	 * The other way is to set zero length session ID when the
	 * ticket is presented and rely on the handshake to determine
	 * session resumption.
	 *
	 * We choose the former approach because this fits in with
	 * assumptions elsewhere in OpenSSL. The session ID is set
	 * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
	 * ticket.
	 */
	EVP_Digest(p, ticklen,
			s->session->session_id, &s->session->session_id_length,
#ifndef OPENSSL_NO_SHA256
							EVP_sha256(), NULL);
#else
							EVP_sha1(), NULL);
#endif
	ret=1;
	return(ret);
f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
	return(-1);
	}

int ssl3_get_cert_status(SSL *s)
```

### ssl/ssl_err.c

#### region() [lines 206-292]
```c
{ERR_FUNC(SSL_F_SSL_CTRL),	"SSL_ctrl"},
{ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"},
{ERR_FUNC(SSL_F_SSL_CTX_MAKE_PROFILES),	"SSL_CTX_MAKE_PROFILES"},
{ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST),	"SSL_CTX_set_trust"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE),	"SSL_CTX_use_certificate"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),	"SSL_CTX_use_certificate_ASN1"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE),	"SSL_CTX_use_certificate_chain_file"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),	"SSL_CTX_use_certificate_file"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),	"SSL_CTX_use_PrivateKey"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),	"SSL_CTX_use_PrivateKey_ASN1"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),	"SSL_CTX_use_PrivateKey_file"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT),	"SSL_CTX_use_psk_identity_hint"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),	"SSL_CTX_use_RSAPrivateKey"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),	"SSL_CTX_use_RSAPrivateKey_ASN1"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),	"SSL_CTX_use_RSAPrivateKey_file"},
{ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE),	"SSL_do_handshake"},
{ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION),	"SSL_GET_NEW_SESSION"},
{ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION),	"SSL_GET_PREV_SESSION"},
{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT),	"SSL_GET_SERVER_SEND_CERT"},
{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY),	"SSL_GET_SERVER_SEND_PKEY"},
{ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY),	"SSL_GET_SIGN_PKEY"},
{ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER),	"SSL_INIT_WBIO_BUFFER"},
{ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),	"SSL_load_client_CA_file"},
{ERR_FUNC(SSL_F_SSL_NEW),	"SSL_new"},
{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),	"SSL_PARSE_CLIENTHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT),	"SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),	"SSL_PARSE_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT),	"SSL_PARSE_SERVERHELLO_USE_SRTP_EXT"},
{ERR_FUNC(SSL_F_SSL_PEEK),	"SSL_peek"},
{ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),	"SSL_PREPARE_CLIENTHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),	"SSL_PREPARE_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
{ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
{ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
{ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
{ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
{ERR_FUNC(SSL_F_SSL_SESSION
/* ... truncated ... */
```

### ssl/ssl_locl.h

#### ssl_sess_cert_free() [lines 796-882]
```c
		dtls1_ctrl, \
		ssl3_ctx_ctrl, \
		ssl3_get_cipher_by_char, \
		ssl3_put_cipher_by_char, \
		ssl3_pending, \
		ssl3_num_ciphers, \
		dtls1_get_cipher, \
		s_get_meth, \
		dtls1_default_timeout, \
		&DTLSv1_enc_data, \
		ssl_undefined_void_function, \
		ssl3_callback_ctrl, \
		ssl3_ctx_callback_ctrl, \
	}; \
	return &func_name##_data; \
	}

struct openssl_ssl_test_functions
	{
	int (*p_ssl_init_wbio_buffer)(SSL *s, int push);
	int (*p_ssl3_setup_buffers)(SSL *s);
	int (*p_tls1_process_heartbeat)(SSL *s);
	int (*p_dtls1_process_heartbeat)(SSL *s);
	};

#ifndef OPENSSL_UNIT_TEST

void ssl_clear_cipher_ctx(SSL *s);
int ssl_clear_bad_session(SSL *s);
CERT *ssl_cert_new(void);
CERT *ssl_cert_dup(CERT *cert);
int ssl_cert_inst(CERT **o);
void ssl_cert_free(CERT *c);
SESS_CERT *ssl_sess_cert_new(void);
void ssl_sess_cert_free(SESS_CERT *sc);
int ssl_set_peer_cert_type(SESS_CERT *c, int type);
int ssl_get_new_session(SSL *s, int session);
int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
				  ssl_cipher_id);
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
			const SSL_CIPHER * const *bp);
STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
					       STACK_OF(SSL_CIPHER) **skp);
int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                             int (*put_cb)(const SSL_CIPHER *, unsigned char *));
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
					     STACK_OF(SSL_CIPHER) **pref,
					     STACK_OF(SSL_CIPHER) **sorted,
					     const char *rule_str);
void ssl_update_cache(SSL *s, int mode);
int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
		       const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);
int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
int ssl_undefined_function(SSL *s);
int ssl_undefined_void_function(void);
int ssl_undefined_const_function(const SSL *s);
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
X509 *ssl_get_server_send_cert(const SSL *);
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
int ssl_verify_alarm_type(long type);
void ssl_load_ciphers(void);
int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);

int ssl2_enc_init(SSL *s, int client);
int ssl2_generate_key_material(SSL *s);
void ssl2_enc(SSL *s,int send_data);
void ssl2_mac(SSL *s,unsigned char *mac,int send_data);
const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p);
int ssl2_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
int ssl2_part_read(SSL *s, unsigned long f, int i);
int ssl2_do_write(SSL *s);
int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data);
void ssl2_return_
/* ... truncated ... */
```

### ssl/ssl_sess.c

#### region() [lines 185-271]
```c
	return(CRYPTO_get_ex_data(&s->ex_data,idx));
	}

SSL_SESSION *SSL_SESSION_new(void)
	{
	SSL_SESSION *ss;

	ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
	if (ss == NULL)
		{
		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
		return(0);
		}
	memset(ss,0,sizeof(SSL_SESSION));

	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
	ss->references=1;
	ss->timeout=60*5+4; /* 5 minute timeout by default */
	ss->time=(unsigned long)time(NULL);
	ss->prev=NULL;
	ss->next=NULL;
	ss->compress_meth=0;
#ifndef OPENSSL_NO_TLSEXT
	ss->tlsext_hostname = NULL;
#ifndef OPENSSL_NO_EC
	ss->tlsext_ecpointformatlist_length = 0;
	ss->tlsext_ecpointformatlist = NULL;
	ss->tlsext_ellipticcurvelist_length = 0;
	ss->tlsext_ellipticcurvelist = NULL;
#endif
#endif
	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
#ifndef OPENSSL_NO_PSK
	ss->psk_identity_hint=NULL;
	ss->psk_identity=NULL;
#endif
#ifndef OPENSSL_NO_SRP
	ss->srp_username=NULL;
#endif
	return(ss);
	}

const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
	{
	if(len)
		*len = s->session_id_length;
	return s->session_id;
	}

unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
	{
	return s->compress_meth;
	}

/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
 * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
 * until we have no conflict is going to complete in one iteration pretty much
 * "most" of the time (btw: understatement). So, if it takes us 10 iterations
 * and we still can't avoid a conflict - well that's a reasonable point to call
 * it quits. Either the RAND code is broken or someone is trying to open roughly
 * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
 * store that many sessions is perhaps a more interesting question ... */

#define MAX_SESS_ID_ATTEMPTS 10
static int def_generate_session_id(const SSL *ssl, unsigned char *id,
				unsigned int *id_len)
{
	unsigned int retry = 0;
	do
		if (RAND_pseudo_bytes(id, *id_len) <= 0)
			return 0;
	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
		(++retry < MAX_SESS_ID_ATTEMPTS));
	if(retry < MAX_SESS_ID_ATTEMPTS)
		return 1;
	/* else - woops a session_id match */
	/* XXX We should also check the external cache --
	 * but the probability of a collision is negligible, and
	 * we could not prevent the concurrent creation of sessions
	 * with identical IDs since we currently don't have means
	 * to atomically check whether a session ID already exists
	 * and make a reservation for it if it does not
	 * (this problem applies to the internal cache as well).
	 */
	return 0;
}

```

## Upstream Fix
```diff
commit 98ece4eebfb6cd45cc8d550c6ac0022965071afc
Author: Matt Caswell <matt@openssl.org>
Date:   Mon May 18 16:27:48 2015 +0100

    Fix race condition in NewSessionTicket

    If a NewSessionTicket is received by a multi-threaded client when
    attempting to reuse a previous ticket then a race condition can occur
    potentially leading to a double free of the ticket data.

    CVE-2015-1791

    This also fixes RT#3808 where a session ID is changed for a session already
    in the client session cache. Since the session ID is the key to the cache
    this breaks the cache access.

    Parts of this patch were inspired by this Akamai change:
    https://github.com/akamai/openssl/commit/c0bf69a791239ceec64509f9f19fcafb2461b0d3

    Reviewed-by: Rich Salz <rsalz@openssl.org>

commit 907f04a30354615e54beaa2bc0b986083f7793ee
Author: Matt Caswell <matt@openssl.org>
Date:   Thu Jun 11 01:30:06 2015 +0100

    More ssl_session_dup fixes

    Fix error handling in ssl_session_dup, as well as incorrect setting up of
    the session ticket. Follow on from CVE-2015-1791.

    Thanks to LibreSSL project for reporting these issues.

    Conflicts:
    	ssl/ssl_sess.c

    Reviewed-by: Tim Hudson <tjh@openssl.org>

Index: openssl-1.0.1i/ssl/ssl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl.h	2015-06-12 19:15:13.279975926 +0200
@@ -2254,6 +2254,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESSION_SET1_ID_CONTEXT		 312
Index: openssl-1.0.1i/ssl/s3_clnt.c
===================================================================
--- openssl-1.0.1i.orig/ssl/s3_clnt.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/s3_clnt.c	2015-06-12 19:15:13.279975926 +0200
@@ -2105,6 +2105,38 @@ int ssl3_get_new_session_ticket(SSL *s)
 		}

 	p=d=(unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
Index: openssl-1.0.1i/ssl/ssl_err.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_err.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_err.c	2015-06-12 19:15:13.280975939 +0200
@@ -245,6 +245,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"},
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
 {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT),	"SSL_SESSION_set1_id_context"},
Index: openssl-1.0.1i/ssl/ssl_locl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_locl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_locl.h	2015-06-12 19:15:13.280975939 +0200
@@ -835,6 +835,7 @@ void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
 				  ssl_cipher_id);
Index: openssl-1.0.1i/ssl/ssl_sess.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_sess.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_sess.c	2015-06-12 19:26:20.502163556 +0200
@@ -224,6 +224,129 @@ SSL_SESSION *SSL_SESSION_new(void)
 	return(ss);
 	}

+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+     /* Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+#ifndef OPENSSL_NO_PSK
+    dest->psk_identity_hint = NULL;
+    dest->psk_identity = NULL;
+#endif
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+# ifndef OPENSSL_NO_EC
+    dest->tlsext_ecpointformatlist = NULL;
+    dest->tlsext_ellipticcurvelist = NULL;
+# endif
+#endif
+    dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+    dest->srp_username = NULL;
+#endif
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+#ifndef OPENSSL_NO_PSK
+    if (src->psk_identity_hint) {
+        dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
+        if (dest->psk_identity_hint == NULL) {
+            goto err;
+        }
+    }
+    if (src->psk_identity) {
+        dest->psk_identity = BUF_strdup(src->psk_identity);
+        if (dest->psk_identity == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+# ifndef OPENSSL_NO_EC
+    if (src->tlsext_ecpointformatlist) {
+        dest->tlsext_ecpointformatlist =
+            BUF_memdup(src->tlsext_ecpointformatlist,
+                       src->tlsext_ecpointformatlist_length);
+        if (dest->tlsext_ecpointformatlist == NULL)
+            goto err;
+    }
+    if (src->tlsext_ellipticcurvelist) {
+        dest->tlsext_ellipticcurvelist =
+            BUF_memdup(src->tlsext_ellipticcurvelist,
+                       src->t
... (truncated)
```

Generate a backported patch for the SUSE target version.

[Assistant]
commit 98ece4eebfb6cd45cc8d550c6ac0022965071afc
Author: Matt Caswell <matt@openssl.org>
Date:   Mon May 18 16:27:48 2015 +0100

    Fix race condition in NewSessionTicket

    If a NewSessionTicket is received by a multi-threaded client when
    attempting to reuse a previous ticket then a race condition can occur
    potentially leading to a double free of the ticket data.

    CVE-2015-1791

    This also fixes RT#3808 where a session ID is changed for a session already
    in the client session cache. Since the session ID is the key to the cache
    this breaks the cache access.

    Parts of this patch were inspired by this Akamai change:
    https://github.com/akamai/openssl/commit/c0bf69a791239ceec64509f9f19fcafb2461b0d3

    Reviewed-by: Rich Salz <rsalz@openssl.org>

commit 907f04a30354615e54beaa2bc0b986083f7793ee
Author: Matt Caswell <matt@openssl.org>
Date:   Thu Jun 11 01:30:06 2015 +0100

    More ssl_session_dup fixes

    Fix error handling in ssl_session_dup, as well as incorrect setting up of
    the session ticket. Follow on from CVE-2015-1791.

    Thanks to LibreSSL project for reporting these issues.

    Conflicts:
    	ssl/ssl_sess.c

    Reviewed-by: Tim Hudson <tjh@openssl.org>

Index: openssl-1.0.1i/ssl/ssl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl.h	2015-06-12 19:15:13.279975926 +0200
@@ -2254,6 +2254,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESSION_SET1_ID_CONTEXT		 312
Index: openssl-1.0.1i/ssl/s3_clnt.c
===================================================================
--- openssl-1.0.1i.orig/ssl/s3_clnt.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/s3_clnt.c	2015-06-12 19:15:13.279975926 +0200
@@ -2105,6 +2105,38 @@ int ssl3_get_new_session_ticket(SSL *s)
 		}

 	p=d=(unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
Index: openssl-1.0.1i/ssl/ssl_err.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_err.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_err.c	2015-06-12 19:15:13.280975939 +0200
@@ -245,6 +245,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"},
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
 {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT),	"SSL_SESSION_set1_id_context"},
Index: openssl-1.0.1i/ssl/ssl_locl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_locl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_locl.h	2015-06-12 19:15:13.280975939 +0200
@@ -835,6 +835,7 @@ void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
 				  ssl_cipher_id);
Index: openssl-1.0.1i/ssl/ssl_sess.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_sess.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_sess.c	2015-06-12 19:26:20.502163556 +0200
@@ -224,6 +224,129 @@ SSL_SESSION *SSL_SESSION_new(void)
 	return(ss);
 	}

+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+     /* Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+#ifndef OPENSSL_NO_PSK
+    dest->psk_identity_hint = NULL;
+    dest->psk_identity = NULL;
+#endif
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+# ifndef OPENSSL_NO_EC
+    dest->tlsext_ecpointformatlist = NULL;
+    dest->tlsext_ellipticcurvelist = NULL;
+# endif
+#endif
+    dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+    dest->srp_username = NULL;
+#endif
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+#ifndef OPENSSL_NO_PSK
+    if (src->psk_identity_hint) {
+        dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
+        if (dest->psk_identity_hint == NULL) {
+            goto err;
+        }
+    }
+    if (src->psk_identity) {
+        dest->psk_identity = BUF_strdup(src->psk_identity);
+        if (dest->psk_identity == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+# ifndef OPENSSL_NO_EC
+    if (src->tlsext_ecpointformatlist) {
+        dest->tlsext_ecpointformatlist =
+            BUF_memdup(src->tlsext_ecpointformatlist,
+                       src->tlsext_ecpointformatlist_length);
+        if (dest->tlsext_ecpointformatlist == NULL)
+            goto err;
+    }
+    if (src->tlsext_ellipticcurvelist) {
+        dest->tlsext_ellipticcurvelist =
+            BUF_memdup(src->tlsext_ellipticcurvelist,
+                       src->tlsext_ellipticcurvelist_length);
+        if (dest->tlsext_ellipticcurvelist == NULL)
+            goto err;
+    }
+# endif
+#endif
+
+    if (ticket != 0) {
+        dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+        if(dest->tlsext_tick == NULL)
+            goto err;
+    } else {
+        dest->tlsext_tick_lifetime_hint = 0;
+        dest->tlsext_ticklen = 0;
+    }
+
+#ifndef OPENSSL_NO_SRP
+    if (src->srp_username) {
+        dest->srp_username = BUF_strdup(src->srp_username);
+        if (dest->srp_username == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    return dest;
+err:
+    SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+    SSL_SESSION_free(dest);
+    return NULL;
+}
+
+
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
 	{
 	if(len)