summaryrefslogtreecommitdiff
path: root/ext/gd
diff options
context:
space:
mode:
authorJakub Zelenka <bukka@php.net>2016-06-19 17:05:48 +0100
committerJakub Zelenka <bukka@php.net>2016-06-19 17:05:48 +0100
commite63a8540a60e95aa5bd8e269add1b02afcc1b79b (patch)
treeb83a144eec24cc81adab0b9a778f7a730d8df79e /ext/gd
parent7a4cc73641bb3eb878f7184bcbd026ee663cf2a9 (diff)
parent53071e647049f099f7f7a0771ddb63fc2cdd621c (diff)
downloadphp-git-e63a8540a60e95aa5bd8e269add1b02afcc1b79b.tar.gz
Merge branch 'openssl_error_store' into openssl_aead
Diffstat (limited to 'ext/gd')
-rw-r--r--ext/gd/gd.c4
-rw-r--r--ext/gd/libgd/gd.c60
-rw-r--r--ext/gd/libgd/gd_gd2.c6
-rw-r--r--ext/gd/libgd/gd_interpolation.c42
-rw-r--r--ext/gd/libgd/gd_webp.c12
-rw-r--r--ext/gd/libgd/xbm.c2
-rw-r--r--ext/gd/tests/bug43475.phpt59
-rw-r--r--ext/gd/tests/bug43475.pngbin0 -> 4697 bytes
-rw-r--r--ext/gd/tests/bug53640.phpt2
-rw-r--r--ext/gd/tests/bug71912.phpt16
-rw-r--r--ext/gd/tests/bug71952.phpt14
-rw-r--r--ext/gd/tests/bug72227.phpt15
-rw-r--r--ext/gd/tests/bug72337.phpt14
-rw-r--r--ext/gd/tests/github_bug_215.phpt43
-rw-r--r--ext/gd/tests/invalid_neg_size.gd2bin0 -> 1676 bytes
15 files changed, 274 insertions, 15 deletions
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index d863523852..b09990938d 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -4667,6 +4667,10 @@ PHP_FUNCTION(imagescale)
}
}
+ if (tmp_h <= 0 || tmp_w <= 0) {
+ RETURN_FALSE;
+ }
+
new_width = tmp_w;
new_height = tmp_h;
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index b427831672..5c7b5ce1ba 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -1049,11 +1049,13 @@ void gdImageAABlend (gdImagePtr im)
}
}
+static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color);
+
static void gdImageHLine(gdImagePtr im, int y, int x1, int x2, int col)
{
if (im->thick > 1) {
int thickhalf = im->thick >> 1;
- gdImageFilledRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col);
+ _gdImageFilledHRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col);
} else {
if (x2 < x1) {
int t = x2;
@@ -1767,6 +1769,12 @@ void gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
return;
}
+ if (!im->trueColor) {
+ if ((color > (im->colorsTotal - 1)) || (border > (im->colorsTotal - 1)) || (color < 0)) {
+ return;
+ }
+ }
+
restoreAlphaBlending = im->alphaBlendingFlag;
im->alphaBlendingFlag = 0;
@@ -2112,10 +2120,53 @@ void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
}
}
-void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
{
int x, y;
+ if (x1 == x2 && y1 == y2) {
+ gdImageSetPixel(im, x1, y1, color);
+ return;
+ }
+
+ if (x1 > x2) {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+ }
+
+ if (y1 > y2) {
+ y = y1;
+ y1 = y2;
+ y2 = y;
+ }
+
+ if (x1 < 0) {
+ x1 = 0;
+ }
+
+ if (x2 >= gdImageSX(im)) {
+ x2 = gdImageSX(im) - 1;
+ }
+
+ if (y1 < 0) {
+ y1 = 0;
+ }
+
+ if (y2 >= gdImageSY(im)) {
+ y2 = gdImageSY(im) - 1;
+ }
+
+ for (x = x1; (x <= x2); x++) {
+ for (y = y1; (y <= y2); y++) {
+ gdImageSetPixel (im, x, y, color);
+ }
+ }
+}
+
+static void _gdImageFilledVRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int x, y;
if (x1 == x2 && y1 == y2) {
gdImageSetPixel(im, x1, y1, color);
@@ -2157,6 +2208,11 @@ void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int
}
}
+void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ _gdImageFilledVRectangle(im, x1, y1, x2, y2, color);
+}
+
void gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
{
int c;
diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c
index efc6ef47af..6726fee826 100644
--- a/ext/gd/libgd/gd_gd2.c
+++ b/ext/gd/libgd/gd_gd2.c
@@ -145,9 +145,15 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in
cidx = gdCalloc(sidx, 1);
for (i = 0; i < nc; i++) {
if (gdGetInt(&cidx[i].offset, in) != 1) {
+ gdFree(cidx);
goto fail1;
}
if (gdGetInt(&cidx[i].size, in) != 1) {
+ gdFree(cidx);
+ goto fail1;
+ }
+ if (cidx[i].offset < 0 || cidx[i].size < 0) {
+ gdFree(cidx);
goto fail1;
}
}
diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c
index a06e333add..6d703b8b30 100644
--- a/ext/gd/libgd/gd_interpolation.c
+++ b/ext/gd/libgd/gd_interpolation.c
@@ -932,9 +932,6 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
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)) {
@@ -944,6 +941,9 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
}
}
+ 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)));
}
@@ -1059,6 +1059,10 @@ gdImagePtr gdImageScaleTwoPass(const gdImagePtr src, const unsigned int src_widt
gdImagePtr tmp_im;
gdImagePtr dst;
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
+ }
+
/* Convert to truecolor if it isn't; this code requires it. */
if (!src->trueColor) {
gdImagePaletteToTrueColor(src);
@@ -1087,6 +1091,10 @@ gdImagePtr Scale(const gdImagePtr src, const unsigned int src_width, const unsig
{
gdImagePtr tmp_im;
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
+ }
+
tmp_im = gdImageCreateTrueColor(new_width, src_height);
if (tmp_im == NULL) {
return NULL;
@@ -1096,7 +1104,7 @@ gdImagePtr Scale(const gdImagePtr src, const unsigned int src_width, const unsig
_gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height);
_gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height);
- gdFree(tmp_im);
+ gdImageDestroy(tmp_im);
return dst;
}
@@ -1120,6 +1128,10 @@ gdImagePtr gdImageScaleNearestNeighbour(gdImagePtr im, const unsigned int width,
unsigned long dst_offset_y = 0;
unsigned int i;
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
+ }
+
dst_img = gdImageCreateTrueColor(new_width, new_height);
if (dst_img == NULL) {
@@ -1221,6 +1233,10 @@ static gdImagePtr gdImageScaleBilinearPalette(gdImagePtr im, const unsigned int
gdImagePtr new_img;
const int transparent = im->transparent;
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
+ }
+
new_img = gdImageCreateTrueColor(new_width, new_height);
if (new_img == NULL) {
return NULL;
@@ -1313,6 +1329,10 @@ static gdImagePtr gdImageScaleBilinearTC(gdImagePtr im, const unsigned int new_w
long i;
gdImagePtr new_img;
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
+ }
+
new_img = gdImageCreateTrueColor(new_width, new_height);
if (!new_img){
return NULL;
@@ -1412,6 +1432,10 @@ gdImagePtr gdImageScaleBicubicFixed(gdImagePtr src, const unsigned int width, co
unsigned int dst_offset_y = 0;
long i;
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
+ }
+
/* impact perf a bit, but not that much. Implementation for palette
images can be done at a later point.
*/
@@ -1634,7 +1658,11 @@ gdImagePtr gdImageScale(const gdImagePtr src, const unsigned int new_width, cons
gdImagePtr im_scaled = NULL;
if (src == NULL || src->interpolation_id < 0 || src->interpolation_id > GD_METHOD_COUNT) {
- return 0;
+ return NULL;
+ }
+
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
}
switch (src->interpolation_id) {
@@ -1680,6 +1708,10 @@ gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, co
unsigned int i;
gdImagePtr dst;
+ if (new_width == 0 || new_height == 0) {
+ return NULL;
+ }
+
dst = gdImageCreateTrueColor(new_width, new_height);
if (!dst) {
return NULL;
diff --git a/ext/gd/libgd/gd_webp.c b/ext/gd/libgd/gd_webp.c
index eef65f79fb..da0cc9d5b8 100644
--- a/ext/gd/libgd/gd_webp.c
+++ b/ext/gd/libgd/gd_webp.c
@@ -14,6 +14,8 @@ gdImagePtr gdImageCreateFromWebp (FILE * inFile)
{
gdImagePtr im;
gdIOCtx *in = gdNewFileCtx(inFile);
+ if (!in)
+ return 0;
im = gdImageCreateFromWebpCtx(in);
in->gd_free(in);
@@ -37,13 +39,14 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
int width, height;
uint8_t *filedata = NULL;
uint8_t *argb = NULL;
- unsigned char *read, *temp;
size_t size = 0, n;
gdImagePtr im;
int x, y;
uint8_t *p;
do {
+ unsigned char *read, *temp;
+
temp = gdRealloc(filedata, size+GD_WEBP_ALLOC_STEP);
if (temp) {
filedata = temp;
@@ -64,19 +67,19 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
if (WebPGetInfo(filedata,size, &width, &height) == 0) {
zend_error(E_ERROR, "gd-webp cannot get webp info");
- gdFree(temp);
+ gdFree(filedata);
return NULL;
}
im = gdImageCreateTrueColor(width, height);
if (!im) {
- gdFree(temp);
+ gdFree(filedata);
return NULL;
}
argb = WebPDecodeARGB(filedata, size, &width, &height);
if (!argb) {
zend_error(E_ERROR, "gd-webp cannot allocate temporary buffer");
- gdFree(temp);
+ gdFree(filedata);
gdImageDestroy(im);
return NULL;
}
@@ -92,7 +95,6 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
gdFree(filedata);
/* do not use gdFree here, in case gdFree/alloc is mapped to something else than libc */
free(argb);
- gdFree(temp);
im->saveAlphaFlag = 1;
return im;
}
diff --git a/ext/gd/libgd/xbm.c b/ext/gd/libgd/xbm.c
index d127a1d4ff..b351814abb 100644
--- a/ext/gd/libgd/xbm.c
+++ b/ext/gd/libgd/xbm.c
@@ -210,7 +210,7 @@ void gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out)
if (gdImageGetPixel(image, x, y) == fg) {
c |= b;
}
- if ((b == 128) || (x == sx && y == sy)) {
+ if ((b == 128) || (x == sx - 1)) {
b = 1;
if (p) {
gdCtxPrintf(out, ", ");
diff --git a/ext/gd/tests/bug43475.phpt b/ext/gd/tests/bug43475.phpt
new file mode 100644
index 0000000000..b29b9800a5
--- /dev/null
+++ b/ext/gd/tests/bug43475.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Bug #43475 (Thick styled lines have scrambled patterns)
+--SKIPIF--
+<?php
+ if (!extension_loaded('gd')) die("skip gd extension not available\n");
+?>
+--FILE--
+<?php
+require_once __DIR__ . '/similarity.inc';
+
+function setStyleAndThickness($im, $color, $thickness)
+{
+ $style = array();
+ $i = 0;
+ while ($i < 16 * $thickness) {
+ $style[$i++] = $color;
+ }
+ while ($i < 20 * $thickness) {
+ $style[$i++] = IMG_COLOR_TRANSPARENT;
+ }
+ while ($i < 28 * $thickness) {
+ $style[$i++] = $color;
+ }
+ while ($i < 32 * $thickness) {
+ $style[$i++] = IMG_COLOR_TRANSPARENT;
+ }
+ imagesetstyle($im, $style);
+ imagesetthickness($im, $thickness);
+}
+
+$im = imagecreate(800, 800);
+imagecolorallocate($im, 255, 255, 255);
+$black = imagecolorallocate($im, 0, 0, 0);
+
+setStyleAndThickness($im, $black, 1);
+imageline($im, 50, 250, 550, 250, IMG_COLOR_STYLED);
+imageline($im, 550, 250, 550, 750, IMG_COLOR_STYLED);
+imageline($im, 550, 750, 50, 250, IMG_COLOR_STYLED);
+
+setStyleAndThickness($im, $black, 2);
+imageline($im, 100, 200, 600, 200, IMG_COLOR_STYLED);
+imageline($im, 600, 200, 600, 700, IMG_COLOR_STYLED);
+imageline($im, 600, 700, 100, 200, IMG_COLOR_STYLED);
+
+setStyleAndThickness($im, $black, 4);
+imageline($im, 150, 150, 650, 150, IMG_COLOR_STYLED);
+imageline($im, 650, 150, 650, 650, IMG_COLOR_STYLED);
+imageline($im, 650, 650, 150, 150, IMG_COLOR_STYLED);
+
+setStyleAndThickness($im, $black, 6);
+imageline($im, 200, 100, 700, 100, IMG_COLOR_STYLED);
+imageline($im, 700, 100, 700, 600, IMG_COLOR_STYLED);
+imageline($im, 700, 600, 200, 100, IMG_COLOR_STYLED);
+
+$ex = imagecreatefrompng(__DIR__ . '/bug43475.png');
+var_dump(calc_image_dissimilarity($ex, $im) < 1e-5);
+?>
+--EXPECT--
+bool(true)
diff --git a/ext/gd/tests/bug43475.png b/ext/gd/tests/bug43475.png
new file mode 100644
index 0000000000..774270f63d
--- /dev/null
+++ b/ext/gd/tests/bug43475.png
Binary files differ
diff --git a/ext/gd/tests/bug53640.phpt b/ext/gd/tests/bug53640.phpt
index a16b7c24c0..ee875de19a 100644
--- a/ext/gd/tests/bug53640.phpt
+++ b/ext/gd/tests/bug53640.phpt
@@ -12,8 +12,6 @@ $white = imagecolorallocate($im, 255, 255, 255);
imagefilledrectangle($im, 2, 2, 6, 6, $white);
imagexbm($im, NULL);
?>
---XFAIL--
-Padding is not implemented yet
--EXPECT--
#define image_width 9
#define image_height 9
diff --git a/ext/gd/tests/bug71912.phpt b/ext/gd/tests/bug71912.phpt
new file mode 100644
index 0000000000..c86188b0f2
--- /dev/null
+++ b/ext/gd/tests/bug71912.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #71912 (libgd: signedness vulnerability)
+--SKIPIF--
+<?php
+ if(!extension_loaded('gd')){ die('skip gd extension not available'); }
+ if(!function_exists('imagecreatefromgd2')) die('skip imagecreatefromgd2() not available');
+?>
+--FILE--
+<?php
+imagecreatefromgd2(__DIR__ . DIRECTORY_SEPARATOR . "invalid_neg_size.gd2");
+?>
+OK
+--EXPECTF--
+
+Warning: imagecreatefromgd2(): '%s%einvalid_neg_size.gd2' is not a valid GD2 file in %s%ebug71912.php on line %d
+OK
diff --git a/ext/gd/tests/bug71952.phpt b/ext/gd/tests/bug71952.phpt
new file mode 100644
index 0000000000..f1f66bf26d
--- /dev/null
+++ b/ext/gd/tests/bug71952.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Bug #71952 (Corruption inside imageaffinematrixget)
+--SKIPIF--
+<?php
+ if(!extension_loaded('gd')){ die('skip gd extension not available'); }
+?>
+--FILE--
+<?php
+$vals=[str_repeat("A","200"),0,1,2,3,4,5,6,7,8,9];
+imageaffinematrixget(4,$vals[0]);
+var_dump($vals[0]);
+?>
+--EXPECTF--
+string(200) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ No newline at end of file
diff --git a/ext/gd/tests/bug72227.phpt b/ext/gd/tests/bug72227.phpt
new file mode 100644
index 0000000000..6252be7d0e
--- /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
diff --git a/ext/gd/tests/bug72337.phpt b/ext/gd/tests/bug72337.phpt
new file mode 100644
index 0000000000..7b8a869577
--- /dev/null
+++ b/ext/gd/tests/bug72337.phpt
@@ -0,0 +1,14 @@
+--TEST--
+ #72337 segfault in imagescale with new dimensions being <=0)
+--SKIPIF--
+<?php
+ if (!function_exists('imagescale')) die("skip gd extension not available\n");
+?>
+--FILE--
+<?php
+$im = imagecreatetruecolor(1, 1);
+imagescale($im, 0, 0, IMG_BICUBIC_FIXED);
+echo "OK";
+?>
+--EXPECT--
+OK
diff --git a/ext/gd/tests/github_bug_215.phpt b/ext/gd/tests/github_bug_215.phpt
new file mode 100644
index 0000000000..f44a5401e1
--- /dev/null
+++ b/ext/gd/tests/github_bug_215.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Github #215 (imagefilltoborder stack overflow when invalid pallete index used)
+--SKIPIF--
+<?php
+if (!extension_loaded("gd")) die("skip GD not present");
+?>
+--FILE--
+<?php
+$image = imagecreate( 10, 10 );
+$bgd = imagecolorallocate( $image, 0, 0, 0 );
+$border = imagecolorallocate( $image, 255, 0, 0 );
+$fillcolor = imagecolorallocate( $image, 255, 0, 0 );
+
+/* Use unallocated color index */
+imagefilltoborder( $image, 0,0, $border+10, $fillcolor);
+echo "#1 passes\n";
+
+/* Use negative color index */
+imagefilltoborder( $image, 0,0, -$border, $fillcolor);
+echo "#2 passes\n";
+
+
+/* Use unallocated color index */
+imagefilltoborder( $image, 0,0, $border, $fillcolor+10);
+echo "#3 passes\n";
+
+/* Use negative color index */
+imagefilltoborder( $image, 0,0, $border, -$fillcolor);
+echo "#4 passes\n";
+
+
+/* Use negative color index */
+imagefilltoborder( $image, 0,0, $border+10, $fillcolor+10);
+echo "#5 passes";
+
+
+?>
+--EXPECT--
+#1 passes
+#2 passes
+#3 passes
+#4 passes
+#5 passes
diff --git a/ext/gd/tests/invalid_neg_size.gd2 b/ext/gd/tests/invalid_neg_size.gd2
new file mode 100644
index 0000000000..3075f15a81
--- /dev/null
+++ b/ext/gd/tests/invalid_neg_size.gd2
Binary files differ