Skip to content

Commit ec8342c

Browse files
committed
Fix GH-19666: imageconvolution() unexpected nan filter value.
undefined behavior occurs during cast from float to int when the element of the filter matrix is -INF. Port the libgd clamp helper which treats non-finite accumulators as 0 (negative/NaN) or 255 (positive infinity) instead of bailing out, matching upstream libgd 81d7f2e. close GH-22129
1 parent 7727193 commit ec8342c

3 files changed

Lines changed: 57 additions & 5 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- GD:
66
. Fixed bug GH-22121 (Double free in gdImageSetStyle() after
77
overflow-triggered early return). (iliaal)
8+
. Fixed bug GH-19666 (imageconvolution() unexpected nan filter value).
9+
(David Carlier)
810

911
- Intl:
1012
. Fix incorrect argument positions for uninitialized calendar arguments in

ext/gd/libgd/gd_filter.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#else
88
# include <unistd.h>
99
#endif
10+
#include <math.h>
1011
#include <stdlib.h>
1112
#include <time.h>
1213

@@ -20,6 +21,20 @@
2021
/* Begin filters function */
2122
#define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel)
2223

24+
static int gdClampFloatToByte(float value)
25+
{
26+
if (!isfinite(value)) {
27+
return value > 0.0f ? 255 : 0;
28+
}
29+
if (value > 255.0f) {
30+
return 255;
31+
}
32+
if (value < 0.0f) {
33+
return 0;
34+
}
35+
return (int)value;
36+
}
37+
2338
#ifdef _WIN32
2439
# define GD_SCATTER_SEED() (unsigned int)(time(0) * GetCurrentProcessId())
2540
#else
@@ -361,6 +376,7 @@ int gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, flo
361376

362377
for ( y=0; y<src->sy; y++) {
363378
for(x=0; x<src->sx; x++) {
379+
int new_ri, new_gi, new_bi;
364380
new_r = new_g = new_b = 0;
365381
pxl = f(srcback, x, y);
366382
new_a = gdImageAlpha(srcback, pxl);
@@ -379,13 +395,13 @@ int gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, flo
379395
new_g = (new_g/filter_div)+offset;
380396
new_b = (new_b/filter_div)+offset;
381397

382-
new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r);
383-
new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g);
384-
new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b);
398+
new_ri = gdClampFloatToByte(new_r);
399+
new_gi = gdClampFloatToByte(new_g);
400+
new_bi = gdClampFloatToByte(new_b);
385401

386-
new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
402+
new_pxl = gdImageColorAllocateAlpha(src, new_ri, new_gi, new_bi, new_a);
387403
if (new_pxl == -1) {
388-
new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
404+
new_pxl = gdImageColorClosestAlpha(src, new_ri, new_gi, new_bi, new_a);
389405
}
390406
gdImageSetPixel (src, x, y, new_pxl);
391407
}

ext/gd/tests/gh19666.phpt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
GH-19666 (Unexpected nan value in imageconvolution)
3+
--EXTENSIONS--
4+
gd
5+
--FILE--
6+
<?php
7+
$image = imagecreatetruecolor(180, 30);
8+
9+
$gaussian = array(
10+
array(1.0, 2.0, 1.0),
11+
array(2.0, 4.0, 2.0),
12+
array(1.0, 2.0, -INF)
13+
);
14+
15+
var_dump(imageconvolution($image, $gaussian, 16, 0));
16+
17+
$rgba = imagecolorat($image, 0, 0);
18+
$colors = imagecolorsforindex($image, $rgba);
19+
var_dump($colors);
20+
21+
imagedestroy($image);
22+
?>
23+
--EXPECT--
24+
bool(true)
25+
array(4) {
26+
["red"]=>
27+
int(0)
28+
["green"]=>
29+
int(0)
30+
["blue"]=>
31+
int(0)
32+
["alpha"]=>
33+
int(0)
34+
}

0 commit comments

Comments
 (0)