diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2019-01-10 14:03:07 +0100 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2019-01-10 14:05:09 +0100 |
commit | 772b1cb245ebe19e220a2552d1e2b700d15f2c68 (patch) | |
tree | 1daff0a9797f361521be6bbafb98164a321c3a7f /ext | |
parent | 5d33024a5dc40a45c986deb37282e54e80058b6f (diff) | |
download | php-git-772b1cb245ebe19e220a2552d1e2b700d15f2c68.tar.gz |
Fix #77272: imagescale() may return image resource on failure
`_gdScaleHoriz()` and `_gdScaleVert()` may fail, but don't signal
failure since they are void functions. We change that according to
upstream libgd.
We also remove the unused `Scale()` function, which doesn't exist in
upstream libgd either, right away.
Diffstat (limited to 'ext')
-rw-r--r-- | ext/gd/libgd/gd_interpolation.c | 43 | ||||
-rw-r--r-- | ext/gd/tests/bug77272.phpt | 21 |
2 files changed, 38 insertions, 26 deletions
diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index e3cd741f8a..81395cb87e 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -1021,7 +1021,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; @@ -1036,13 +1036,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) @@ -1068,7 +1069,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; @@ -1083,19 +1084,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; @@ -1111,7 +1114,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) { @@ -1119,30 +1126,14 @@ 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); - - return dst; -} - -gdImagePtr Scale(const gdImagePtr src, const unsigned int src_width, const unsigned int src_height, const gdImagePtr dst, const unsigned int new_width, const unsigned int new_height) -{ - gdImagePtr tmp_im; - - if (new_width == 0 || new_height == 0) { - return NULL; - } - - tmp_im = gdImageCreateTrueColor(new_width, src_height); - if (tmp_im == NULL) { + scale_pass_res = _gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height); + if (scale_pass_res != 1) { + gdImageDestroy(dst); + gdImageDestroy(tmp_im); return NULL; } - gdImageSetInterpolationMethod(tmp_im, src->interpolation_id); - - _gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height); - _gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height); - gdImageDestroy(tmp_im); + return dst; } diff --git a/ext/gd/tests/bug77272.phpt b/ext/gd/tests/bug77272.phpt new file mode 100644 index 0000000000..e3423da543 --- /dev/null +++ b/ext/gd/tests/bug77272.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #77272 (imagescale() may return image resource on failure) +--INI-- +memory_limit=-1 +--SKIPIF-- +<?php +if (!extension_loaded('gd')) die('skip gd extension not available'); +if (!GD_BUNGLED && version_compare(GD_VERSION, '2.2.5', '<=')) die('skip upstream fix not yet released'); +if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); +?> +--FILE-- +<?php +$img = imagecreate(2**28, 1); +var_dump(imagescale($img, 1, 1, IMG_TRIANGLE)); +?> +===DONE=== +--EXPECTF-- +Warning: imagescale():%S product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully + in %s on line %d +bool(false) +===DONE=== |