CVE-2016-5767: Integer Overflow or Wraparound (CWE-190)
value: Integer overflow in the gdImageCreate function in gd.c in the GD Graphics Library (aka libgd) before 2.0.34RC1, as used in PHP before 5.5.37, 5.6.x before 5.6.23, and 7.x before 7.0.8, allows remote attackers to cause a denial of service (heap-based buffer overflow and application crash) or possibly have unspecified other impact via a crafted image dimensions.
CWE description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
CVSS v3 base score: 8.8
Published: 2016-08-07T10:59Z
Repository: https://github.com/php/php-src
Language: Other
Files changed: NEWS, ext/gd/libgd/gd.c
Commit date: 2016-06-20 23:58:26 -0700
Commit message: iFixed bug #72446 - Integer Overflow in gdImagePaletteToTrueColor() resulting in heap overflow

Diff: diff --git a/NEWS b/NEWS
index fffc443a7cf..6f1461c2f9e 100644
--- a/NEWS
+++ b/NEWS
@@ -16,10 +16,12 @@ PHP                                                                        NEWS
     (cmb)
   . Fixed bug #72298 (pass2_no_dither out-of-bounds access). (Stas)
   . Fixed bug #72339 (Integer Overflow in _gd2GetHeader() resulting in 
     heap overflow). (Pierre)
   . Fixed bug #72407 (NULL Pointer Dereference at _gdScaleVert). (Stas)
+  . Fixed bug #72446 (Integer Overflow in gdImagePaletteToTrueColor() resulting
+    in heap overflow). (Pierre)
 
 - mbstring:
    . Fixed bug #72402 (_php_mb_regex_ereg_replace_exec - double free). (Stas)
 
 - mcrypt:
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index 2c63aac4cd4..4dad95ae393 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -131,10 +131,14 @@ gdImagePtr gdImageCreate (int sx, int sy)
 
 	if (overflow2(sizeof(unsigned char *), sy)) {
 		return NULL;
 	}
 
+	if (overflow2(sizeof(unsigned char *), sx)) {
+		return NULL;
+	}
+
 	im = (gdImage *) gdCalloc(1, sizeof(gdImage));
 
 	/* Row-major ever since gd 1.3 */
 	im->pixels = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy);
 	im->AA_opacity = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy);
@@ -1096,16 +1100,16 @@ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
 	int wid;
 	int w, wstart;
 	int thick = im->thick;
 
 	if (color == gdAntiAliased) {
-		/* 
+		/*
 		   gdAntiAliased passed as color: use the much faster, much cheaper
 		   and equally attractive gdImageAALine implementation. That
 		   clips too, so don't clip twice.
 		   */
-		gdImageAALine(im, x1, y1, x2, y2, im->AA_color); 
+		gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
 		return;
 	}
 
 	/* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no points need to be drawn */
 	if (!clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) || !clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im))) {
@@ -1878,11 +1882,11 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc)
 
 	if (!im->trueColor && nc > (im->colorsTotal -1)) {
 		return;
 	}
 
-	alphablending_bak = im->alphaBlendingFlag;	
+	alphablending_bak = im->alphaBlendingFlag;
 	im->alphaBlendingFlag = 0;
 
 	if (nc==gdTiled){
 		_gdImageFillTiled(im,x,y,nc);
 		im->alphaBlendingFlag = alphablending_bak;
@@ -1890,11 +1894,11 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc)
 	}
 
 	wx2=im->sx;wy2=im->sy;
 	oc = gdImageGetPixel(im, x, y);
 	if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) {
-		im->alphaBlendingFlag = alphablending_bak;	
+		im->alphaBlendingFlag = alphablending_bak;
 		return;
 	}
 
 	/* Do not use the 4 neighbors implementation with
 	 * small images
@@ -1953,11 +1957,11 @@ skip:			for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++);
 	}
 
 	efree(stack);
 
 done:
-	im->alphaBlendingFlag = alphablending_bak;	
+	im->alphaBlendingFlag = alphablending_bak;
 }
 
 static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc)
 {
 	int i, l, x1, x2, dy;
@@ -2059,11 +2063,11 @@ void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
 		int cx, cy, x1ul, y1ul, x2lr, y2lr;
 		int half = thick >> 1;
 
 		x1ul = x1 - half;
 		y1ul = y1 - half;
-		
+
 		x2lr = x2 + half;
 		y2lr = y2 + half;
 
 		cy = y1ul + thick;
 		while (cy-- > y1ul) {
@@ -2257,11 +2261,11 @@ void gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int s
 	int c, dc;
 	int x, y;
 	int tox, toy;
 	int ncR, ncG, ncB;
 	toy = dstY;
-	
+
 	for (y = srcY; y < (srcY + h); y++) {
 		tox = dstX;
 		for (x = srcX; x < (srcX + w); x++) {
 			int nc;
 			c = gdImageGetPixel(src, x, y);
@@ -2354,11 +2358,11 @@ void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int
 	int ydest;
 	int i;
 	int colorMap[gdMaxColors];
 	/* Stretch vectors */
 	int *stx, *sty;
-	
+
 	if (overflow2(sizeof(int), srcW)) {
 		return;
 	}
 	if (overflow2(sizeof(int), srcH)) {
 		return;
@@ -2899,11 +2903,11 @@ int gdAlphaBlend (int dst, int src) {
 /*      overlay becomes quite opaque.                                   */
 /* -------------------------------------------------------------------- */
     src_weight = gdAlphaTransparent - src_alpha;
     dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax;
     tot_weight = src_weight + dst_weight;
-    
+
 /* -------------------------------------------------------------------- */
 /*      What red, green and blue result values will we use?             */
 /* -------------------------------------------------------------------- */
     alpha = src_alpha * dst_alpha / gdAlphaMax;
 

Vulnerable code: 		/* 
		gdImageAALine(im, x1, y1, x2, y2, im->AA_color); 
	alphablending_bak = im->alphaBlendingFlag;	
		im->alphaBlendingFlag = alphablending_bak;	
	im->alphaBlendingFlag = alphablending_bak;	
		
	
	
    
Fixed code:   . Fixed bug #72446 (Integer Overflow in gdImagePaletteToTrueColor() resulting
    in heap overflow). (Pierre)
	if (overflow2(sizeof(unsigned char *), sx)) {
		return NULL;
	}

		/*
		gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
	alphablending_bak = im->alphaBlendingFlag;
		im->alphaBlendingFlag = alphablending_bak;
	im->alphaBlendingFlag = alphablending_bak;