Description: fix OOB or OOM in gdImageScale
Origin: backport, https://github.com/libgd/libgd/commit/0dd40abd6d5b3e53a6b745dd4d6cf94b70010989
Origin: backport, https://github.com/libgd/libgd/commit/d325888a9fe3c9681e4a9aad576de2c5cd5df2ef
Origin: backport, https://github.com/libgd/libgd/commit/ff9113c80a32205d45205d3ea30965b25480e0fb
Origin: backport, https://github.com/libgd/libgd/commit/f60ec7a546499f9446063a4dbe755be9523d8232
Origin: backport, https://github.com/libgd/libgd/commit/7a28c235890c95e6010e7b0d0f7c7369367168ef
Origin: backport, https://github.com/libgd/libgd/commit/0dd1706c14abced200f8e5f83d2f86dc44cd9508
Origin: backport, https://github.com/libgd/libgd/commit/8b7e76dd370e068515162e74986f7968dddc7384
Bug-PHP: https://bugs.php.net/bug.php?id=72558

Index: libgd2-2.1.0/src/gd.c
===================================================================
--- libgd2-2.1.0.orig/src/gd.c	2016-08-09 10:01:26.494915347 -0400
+++ libgd2-2.1.0/src/gd.c	2016-08-09 10:01:26.490915294 -0400
@@ -207,7 +207,7 @@
 		return 0;
 	}
 
-	if (overflow2(sizeof(int), sx)) {
+	if (overflow2(sizeof(int *), sx)) {
 		return NULL;
 	}
 
@@ -2781,78 +2781,77 @@
 										int dstW, int dstH, int srcW, int srcH)
 {
 	int x, y;
-	double sy1, sy2, sx1, sx2;
 	if (!dst->trueColor) {
-		gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH,
-		                    srcW, srcH);
+		gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
 		return;
 	}
 	for (y = dstY; (y < dstY + dstH); y++) {
-		sy1 = ((double) y - (double) dstY) * (double) srcH / (double) dstH;
-		sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH /
-		      (double) dstH;
 		for (x = dstX; (x < dstX + dstW); x++) {
-			double sx, sy;
-			double spixels = 0;
-			double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
-			double alpha_sum = 0.0, contrib_sum = 0.0;
-
-			sx1 = ((double) x - (double) dstX) * (double) srcW / dstW;
-			sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / dstW;
+			float sy1, sy2, sx1, sx2;
+			float sx, sy;
+			float spixels = 0.0;
+			float red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
+			float alpha_factor, alpha_sum = 0.0, contrib_sum = 0.0;
+			sy1 = ((float)(y - dstY)) * (float)srcH / (float)dstH;
+			sy2 = ((float)(y + 1 - dstY)) * (float) srcH / (float) dstH;
 			sy = sy1;
 			do {
-				double yportion;
-				if (floor2 (sy) == floor2 (sy1)) {
-					yportion = 1.0 - (sy - floor2 (sy));
+				float yportion;
+				if (floorf(sy) == floorf(sy1)) {
+					yportion = 1.0 - (sy - floorf(sy));
 					if (yportion > sy2 - sy1) {
 						yportion = sy2 - sy1;
 					}
-					sy = floor2 (sy);
-				} else if (sy == floor2 (sy2)) {
-					yportion = sy2 - floor2 (sy2);
+					sy = floorf(sy);
+				} else if (sy == floorf(sy2)) {
+					yportion = sy2 - floorf(sy2);
 				} else {
 					yportion = 1.0;
 				}
+				sx1 = ((float)(x - dstX)) * (float) srcW / dstW;
+				sx2 = ((float)(x + 1 - dstX)) * (float) srcW / dstW;
 				sx = sx1;
 				do {
-					double xportion;
-					double pcontribution;
+					float xportion;
+					float pcontribution;
 					int p;
-					if (floor2 (sx) == floor2 (sx1)) {
-						xportion = 1.0 - (sx - floor2 (sx));
+					if (floorf(sx) == floorf(sx1)) {
+						xportion = 1.0 - (sx - floorf(sx));
 						if (xportion > sx2 - sx1) {
 							xportion = sx2 - sx1;
 						}
-						sx = floor2 (sx);
-					} else if (sx == floor2 (sx2)) {
-						xportion = sx2 - floor2 (sx2);
+						sx = floorf(sx);
+					} else if (sx == floorf(sx2)) {
+						xportion = sx2 - floorf(sx2);
 					} else {
 						xportion = 1.0;
 					}
 					pcontribution = xportion * yportion;
-					/* 2.08: previously srcX and srcY were ignored.
-					   Andrew Pattison */
-					p = gdImageGetTrueColorPixel (src,
-					                              (int) sx + srcX,
-					                              (int) sy + srcY);
-					red += gdTrueColorGetRed (p) * pcontribution;
-					green += gdTrueColorGetGreen (p) * pcontribution;
-					blue += gdTrueColorGetBlue (p) * pcontribution;
+					p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY);
+
+					alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution;
+					red += gdTrueColorGetRed (p) * alpha_factor;
+					green += gdTrueColorGetGreen (p) * alpha_factor;
+					blue += gdTrueColorGetBlue (p) * alpha_factor;
 					alpha += gdTrueColorGetAlpha (p) * pcontribution;
+					alpha_sum += alpha_factor;
+					contrib_sum += pcontribution;
 					spixels += xportion * yportion;
 					sx += 1.0;
-				} while (sx < sx2);
-				sy += 1.0;
-			} while (sy < sy2);
+				}
+				while (sx < sx2);
+				sy += 1.0f;
+			}
+			while (sy < sy2);
+
 			if (spixels != 0.0) {
 				red /= spixels;
 				green /= spixels;
 				blue /= spixels;
 				alpha /= spixels;
-				alpha += 0.5;
 			}
-			if ( alpha_sum != 0.0f) {
-				if( contrib_sum != 0.0f) {
+			if ( alpha_sum != 0.0) {
+				if( contrib_sum != 0.0) {
 					alpha_sum /= contrib_sum;
 				}
 				red /= alpha_sum;
@@ -2866,17 +2865,13 @@
 			if (green > 255.0) {
 				green = 255.0;
 			}
-			if (blue > 255.0) {
+			if (blue > 255.0f) {
 				blue = 255.0;
 			}
 			if (alpha > gdAlphaMax) {
 				alpha = gdAlphaMax;
 			}
-			gdImageSetPixel (dst,
-			                 x, y,
-			                 gdTrueColorAlpha ((int) red,
-			                                   (int) green,
-			                                   (int) blue, (int) alpha));
+			gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha));
 		}
 	}
 }
Index: libgd2-2.1.0/src/gd_interpolation.c
===================================================================
--- libgd2-2.1.0.orig/src/gd_interpolation.c	2016-08-09 10:01:26.494915347 -0400
+++ libgd2-2.1.0/src/gd_interpolation.c	2016-08-09 10:01:38.947079605 -0400
@@ -901,6 +901,7 @@
 {
 	unsigned int u = 0;
 	LineContribType *res;
+	int overflow_error = 0;
 
 	res = (LineContribType *) gdMalloc(sizeof(LineContribType));
 	if (!res) {
@@ -908,10 +909,31 @@
 	}
 	res->WindowSize = windows_size;
 	res->LineLength = line_length;
+	if (overflow2(line_length, sizeof(ContributionType))) {
+		gdFree(res);
+		return NULL;
+	}
 	res->ContribRow = (ContributionType *) gdMalloc(line_length * sizeof(ContributionType));
-
+	if (res->ContribRow == NULL) {
+		gdFree(res);
+		return NULL;
+	}
 	for (u = 0 ; u < line_length ; u++) {
-		res->ContribRow[u].Weights = (double *) gdMalloc(windows_size * sizeof(double));
+		if (overflow2(windows_size, sizeof(double))) {
+			overflow_error = 1;
+		} else {
+			res->ContribRow[u].Weights = (double *) gdMalloc(windows_size * sizeof(double));
+		}
+		if (overflow_error == 1 || res->ContribRow[u].Weights == NULL) {
+			unsigned int i;
+			u--;
+			for (i=0;i<=u;i++) {
+				gdFree(res->ContribRow[i].Weights);
+			}
+			gdFree(res->ContribRow);
+			gdFree(res);
+			return NULL;
+		}
 	}
 	return res;
 }
@@ -944,7 +966,9 @@
 
 	windows_size = 2 * (int)ceil(width_d) + 1;
 	res = _gdContributionsAlloc(line_size, windows_size);
-
+	if (res == NULL) {
+		return NULL;
+	}
 	for (u = 0; u < line_size; u++) {
 		const double dCenter = (double)u / scale_d;
 		/* get the significant edge points affecting the pixel */
@@ -1007,7 +1031,7 @@
 	}
 }
 
-static inline void _gdScaleHoriz(gdImagePtr pSrc, unsigned int src_width, unsigned int src_height, gdImagePtr pDst,  unsigned int dst_width, unsigned int dst_height)
+static inline int _gdScaleHoriz(gdImagePtr pSrc, unsigned int src_width, unsigned int src_height, gdImagePtr pDst,  unsigned int dst_width, unsigned int dst_height)
 {
 	unsigned int u;
 	LineContribType * contrib;
@@ -1022,13 +1046,14 @@
 
 	contrib = _gdContributionsCalc(dst_width, src_width, (double)dst_width / (double)src_width, pSrc->interpolation);
 	if (contrib == NULL) {
-		return;
+		return 0;
 	}
 	/* Scale each row */
 	for (u = 0; u < dst_height - 1; u++) {
 		_gdScaleRow(pSrc, src_width, pDst, dst_width, u, contrib);
 	}
 	_gdContributionsFree (contrib);
+	return 1;
 }
 
 static inline void _gdScaleCol (gdImagePtr pSrc,  unsigned int src_width, gdImagePtr pRes, unsigned int dst_width, unsigned int dst_height, unsigned int uCol, LineContribType *contrib)
@@ -1053,7 +1078,7 @@
 	}
 }
 
-static inline void _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_width, const unsigned int src_height, const gdImagePtr pDst, const unsigned int dst_width, const unsigned int dst_height)
+static inline int _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_width, const unsigned int src_height, const gdImagePtr pDst, const unsigned int dst_width, const unsigned int dst_height)
 {
 	unsigned int u;
 	LineContribType * contrib;
@@ -1067,11 +1092,15 @@
 	}
 
 	contrib = _gdContributionsCalc(dst_height, src_height, (double)(dst_height) / (double)(src_height), pSrc->interpolation);
+	if (contrib == NULL) {
+		return 0;
+	}
 	/* scale each column */
 	for (u = 0; u < dst_width - 1; u++) {
 		_gdScaleCol(pSrc, src_width, pDst, dst_width, dst_height, u, contrib);
 	}
 	_gdContributionsFree(contrib);
+	return 1;
 }
 
 gdImagePtr gdImageScaleTwoPass(const gdImagePtr src, const unsigned int src_width, const unsigned int src_height, const unsigned int new_width, const unsigned int new_height)
@@ -1083,14 +1112,22 @@
 	if (tmp_im == NULL) {
 		return NULL;
 	}
-	_gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height);
+	if (!_gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height)) {
+		gdImageDestroy(tmp_im);
+		return NULL;
+	}
 
 	dst = gdImageCreateTrueColor(new_width, new_height);
 	if (dst == NULL) {
 		gdImageDestroy(tmp_im);
 		return NULL;
 	}
-	_gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height);
+	if (!_gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height)) {
+		gdImageDestroy(tmp_im);
+		gdImageDestroy(dst);
+		return NULL;
+	}
+
 	gdImageDestroy(tmp_im);
 
 	return dst;
