CVE-2013-7456: Out-of-bounds Read (CWE-125)
value: gd_interpolation.c in the GD Graphics Library (aka libgd) before 2.1.1, as used in PHP before 5.5.36, 5.6.x before 5.6.22, and 7.x before 7.0.7, allows remote attackers to cause a denial of service (out-of-bounds read) or possibly have unspecified other impact via a crafted image that is mishandled by the imagescale function.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.6
Published: 2016-08-07T10:59Z
Repository: https://github.com/php/php-src
Language: C
Files changed: ext/gd/libgd/gd_interpolation.c, ext/gd/tests/bug72227.phpt
Commit date: 2016-05-23 00:34:35 -0700
Commit message: Fixed bug #72227: imagescale out-of-bounds read

Ported from https://github.com/libgd/libgd/commit/4f65a3e4eedaffa1efcf9ee1eb08f0b504fbc31a

Diff: diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c
index 6b7360a6def..a0174983830 100644
--- a/ext/gd/libgd/gd_interpolation.c
+++ b/ext/gd/libgd/gd_interpolation.c
@@ -37,12 +37,12 @@
 /*
 	Additional functions are available for simple rotation or up/downscaling.
 	downscaling using the fixed point implementations are usually much faster
 	than the existing gdImageCopyResampled while having a similar or better
 	quality.
-	
-	For image rotations, the optimized versions have a lazy antialiasing for 
+
+	For image rotations, the optimized versions have a lazy antialiasing for
 	the edges of the images. For a much better antialiased result, the affine
 	function is recommended.
 */
 
 /*
@@ -631,11 +631,11 @@ static inline int _color_blend (const int dst, const int src)
 			return ((alpha << 24) + (red << 16) + (green << 8) + blue);
 		}
 	}
 }
 
-static inline int _setEdgePixel(const gdImagePtr src, unsigned int x, unsigned int y, gdFixed coverage, const int bgColor) 
+static inline int _setEdgePixel(const gdImagePtr src, unsigned int x, unsigned int y, gdFixed coverage, const int bgColor)
 {
 	const gdFixed f_127 = gd_itofx(127);
 	register int c = src->tpixels[y][x];
 	c = c | (( (int) (gd_fxtof(gd_mulfx(coverage, f_127)) + 50.5f)) << 24);
 	return _color_blend(bgColor, c);
@@ -932,22 +932,22 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
         register int iLeft = MAX(0, (int)floor (dCenter - width_d));
         int iRight = MIN((int)ceil(dCenter + width_d), (int)src_size - 1);
         double dTotalWeight = 0.0;
 		int iSrc;
 
-        res->ContribRow[u].Left = iLeft;
-        res->ContribRow[u].Right = iRight;
-
         /* Cut edge points to fit in filter window in case of spill-off */
         if (iRight - iLeft + 1 > windows_size)  {
             if (iLeft < ((int)src_size - 1 / 2))  {
                 iLeft++;
             } else {
                 iRight--;
             }
         }
 
+        res->ContribRow[u].Left = iLeft;
+        res->ContribRow[u].Right = iRight;
+
         for (iSrc = iLeft; iSrc <= iRight; iSrc++) {
             dTotalWeight += (res->ContribRow[u].Weights[iSrc-iLeft] =  scale_f_d * (*pFilter)(scale_f_d * (dCenter - (double)iSrc)));
         }
 
 		if (dTotalWeight < 0.0) {
@@ -2271,11 +2271,11 @@ int gdTransformAffineGetImage(gdImagePtr *dst,
 	(*dst)->saveAlphaFlag = 1;
 
 	if (!src->trueColor) {
 		gdImagePaletteToTrueColor(src);
 	}
-	
+
 	/* Translate to dst origin (0,0) */
 	gdAffineTranslate(m, -bbox.x, -bbox.y);
 	gdAffineConcat(m, affine, m);
 
 	gdImageAlphaBlending(*dst, 0);
@@ -2330,11 +2330,11 @@ int gdTransformAffineCopy(gdImagePtr dst,
 
 	/* These methods use special implementations */
 	if (src->interpolation_id == GD_BILINEAR_FIXED || src->interpolation_id == GD_BICUBIC_FIXED || src->interpolation_id == GD_NEAREST_NEIGHBOUR) {
 		interpolation_id_bak = src->interpolation_id;
 		interpolation_bak = src->interpolation;
-		
+
 		gdImageSetInterpolationMethod(src, GD_BICUBIC);
 	}
 
 
 	gdImageClipRectangle(src, src_region);
diff --git a/ext/gd/tests/bug72227.phpt b/ext/gd/tests/bug72227.phpt
new file mode 100644
index 00000000000..6252be7d0eb
--- /dev/null
+++ b/ext/gd/tests/bug72227.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #72227: imagescale out-of-bounds read
+--SKIPIF--
+<?php
+	if (!extension_loaded('gd')) die("skip gd extension not available\n");
+?>
+--FILE--
+<?php
+
+$img = imagecreatetruecolor ( 100, 100);
+imagescale($img, 13, 1, IMG_BICUBIC);
+?>
+DONE
+--EXPECT--
+DONE
\ No newline at end of file

Vulnerable code: 	
	For image rotations, the optimized versions have a lazy antialiasing for 
static inline int _setEdgePixel(const gdImagePtr src, unsigned int x, unsigned int y, gdFixed coverage, const int bgColor) 
        res->ContribRow[u].Left = iLeft;
        res->ContribRow[u].Right = iRight;

	
		
Fixed code: 
	For image rotations, the optimized versions have a lazy antialiasing for
static inline int _setEdgePixel(const gdImagePtr src, unsigned int x, unsigned int y, gdFixed coverage, const int bgColor)
        res->ContribRow[u].Left = iLeft;
        res->ContribRow[u].Right = iRight;



--TEST--
Bug #72227: imagescale out-of-bounds read
--SKIPIF--
<?php
	if (!extension_loaded('gd')) die("skip gd extension not available\n");
?>
--FILE--
<?php

$img = imagecreatetruecolor ( 100, 100);
imagescale($img, 13, 1, IMG_BICUBIC);
?>
DONE
--EXPECT--
DONE