Patch fix-72558 for GD related Bug #72558
Patch version 2016-07-07 14:00 UTC
Return to Bug #72558 |
Download this patch
Patch Revisions:
Developer: cmb
From fc9f1061267b115097eb39abc57cc149df01e46d Mon Sep 17 00:00:00 2001
From: "Christoph M. Becker" <cmb@php.net>
Date: Thu, 7 Jul 2016 15:58:44 +0200
Subject: [PATCH] Bug #72558: Integer overflow error within
_gdContributionsAlloc()
According to the respective patch for external libgd, we fix PHP's bundled
libgd. Namely, we fix the broken overflow check in libgd/gd.c, and we add
additional handling of allocation errors.
---
ext/gd/libgd/gd.c | 4 ++--
ext/gd/libgd/gd_interpolation.c | 47 +++++++++++++++++++++++++++++++++--------
ext/gd/tests/bug72558.phpt | 16 ++++++++++++++
3 files changed, 56 insertions(+), 11 deletions(-)
create mode 100644 ext/gd/tests/bug72558.phpt
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index a5799c5..84e5e5f 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -186,11 +186,11 @@ gdImagePtr gdImageCreateTrueColor (int sx, int sy)
return NULL;
}
- if (overflow2(sizeof(unsigned char *), sy)) {
+ if (overflow2(sizeof(int *), sy)) {
return NULL;
}
- if (overflow2(sizeof(int), sx)) {
+ if (overflow2(sizeof(int *), sx)) {
return NULL;
}
diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c
index 8331996..7a0306e 100644
--- a/ext/gd/libgd/gd_interpolation.c
+++ b/ext/gd/libgd/gd_interpolation.c
@@ -888,9 +888,20 @@ static inline LineContribType * _gdContributionsAlloc(unsigned int line_length,
res->WindowSize = windows_size;
res->LineLength = line_length;
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 (res->ContribRow[u].Weights == NULL) {
+ u--;
+ while (u >= 0) {
+ gdFree(res->ContribRow[u].Weights);
+ u--;
+ }
+ return NULL;
+ }
}
return res;
}
@@ -923,7 +934,9 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
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 */
@@ -986,7 +999,7 @@ static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImage
}
}
-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;
@@ -1001,13 +1014,14 @@ static inline void _gdScaleHoriz(gdImagePtr pSrc, unsigned int src_width, unsign
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)
@@ -1033,7 +1047,7 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
}
}
-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;
@@ -1048,19 +1062,21 @@ static inline void _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_w
contrib = _gdContributionsCalc(dst_height, src_height, (double)(dst_height) / (double)(src_height), pSrc->interpolation);
if (contrib == NULL) {
- return;
+ 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)
{
gdImagePtr tmp_im;
gdImagePtr dst;
+ int scale_pass_res;
if (new_width == 0 || new_height == 0) {
return NULL;
@@ -1076,7 +1092,11 @@ gdImagePtr gdImageScaleTwoPass(const gdImagePtr src, const unsigned int src_widt
return NULL;
}
gdImageSetInterpolationMethod(tmp_im, src->interpolation_id);
- _gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height);
+ scale_pass_res = _gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height);
+ if (scale_pass_res != 1) {
+ gdImageDestroy(tmp_im);
+ return NULL;
+ }
dst = gdImageCreateTrueColor(new_width, new_height);
if (dst == NULL) {
@@ -1084,8 +1104,17 @@ gdImagePtr gdImageScaleTwoPass(const gdImagePtr src, const unsigned int src_widt
return NULL;
}
gdImageSetInterpolationMethod(dst, src->interpolation_id);
- _gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height);
- gdImageDestroy(tmp_im);
+ scale_pass_res = _gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height);
+ if (scale_pass_res != 1) {
+ gdImageDestroy(dst);
+ if (src != tmp_im && tmp_im != NULL) {
+ gdImageDestroy(tmp_im);
+ }
+ return NULL;
+ }
+ if (src != tmp_im && tmp_im != NULL) {
+ gdImageDestroy(tmp_im);
+ }
return dst;
}
diff --git a/ext/gd/tests/bug72558.phpt b/ext/gd/tests/bug72558.phpt
new file mode 100644
index 0000000..e534ba3
--- /dev/null
+++ b/ext/gd/tests/bug72558.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #72558: Integer overflow error within _gdContributionsAlloc()
+--SKIPIF--
+<?php
+if (!extension_loaded('gd')) die('skip gd extension not available');
+?>
+--FILE--
+<?php
+$im = imagecreate(1, 1);
+imagesetinterpolation($im, IMG_BELL);
+imagescale($im, 0x15555556, 1);
+imagedestroy($im);
+?>
+--EXPECTF--
+Warning: imagescale(): gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully
+ in %s on line %d
--
2.8.1.windows.1
|