Skip to content

Commit a6fbab6

Browse files
committed
Fix GH-19730: undefined behavior in gd_interpolation.c.
Port libgd f6202ec0de1c8340cf9b69c4a86c84fc63703207: validate the computed bounding box in gdTransformAffineBoundingBox before casting the floating-point coordinates to int, and propagate the failure through gdTransformAffineGetImage.
1 parent 5dd3909 commit a6fbab6

2 files changed

Lines changed: 48 additions & 5 deletions

File tree

ext/gd/libgd/gd_interpolation.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <stdlib.h>
5858
#include <string.h>
5959
#include <math.h>
60+
#include <limits.h>
6061

6162
#include "gd.h"
6263
#include "gdhelpers.h"
@@ -2245,7 +2246,10 @@ int gdTransformAffineGetImage(gdImagePtr *dst,
22452246
src_area = &area_full;
22462247
}
22472248

2248-
gdTransformAffineBoundingBox(src_area, affine, &bbox);
2249+
if (gdTransformAffineBoundingBox(src_area, affine, &bbox) != GD_TRUE) {
2250+
*dst = NULL;
2251+
return GD_FALSE;
2252+
}
22492253

22502254
*dst = gdImageCreateTrueColor(bbox.width, bbox.height);
22512255
if (*dst == NULL) {
@@ -2421,6 +2425,8 @@ int gdTransformAffineCopy(gdImagePtr dst,
24212425
int gdTransformAffineBoundingBox(gdRectPtr src, const double affine[6], gdRectPtr bbox)
24222426
{
24232427
gdPointF extent[4], min, max, point;
2428+
double width, height;
2429+
int bbox_x, bbox_y, bbox_width, bbox_height;
24242430
int i;
24252431

24262432
extent[0].x=0.0;
@@ -2451,10 +2457,29 @@ int gdTransformAffineBoundingBox(gdRectPtr src, const double affine[6], gdRectPt
24512457
if (max.y < extent[i].y)
24522458
max.y=extent[i].y;
24532459
}
2454-
bbox->x = (int) min.x;
2455-
bbox->y = (int) min.y;
2456-
bbox->width = (int) floor(max.x - min.x) - 1;
2457-
bbox->height = (int) floor(max.y - min.y);
2460+
width = floor(max.x - min.x);
2461+
height = floor(max.y - min.y);
2462+
if (!isfinite(min.x) || !isfinite(min.y) || !isfinite(width) || !isfinite(height)
2463+
|| min.x <= INT_MIN || min.x > INT_MAX
2464+
|| min.y <= INT_MIN || min.y > INT_MAX
2465+
|| width < 1.0 || width > INT_MAX
2466+
|| height < 0.0 || height > INT_MAX) {
2467+
return GD_FALSE;
2468+
}
2469+
bbox_x = (int) min.x;
2470+
bbox_y = (int) min.y;
2471+
bbox_width = (int) width - 1;
2472+
bbox_height = (int) height;
2473+
if ((bbox_x < 0 && bbox_width > INT_MAX + bbox_x)
2474+
|| (bbox_x > 0 && bbox_width > INT_MAX - bbox_x)
2475+
|| (bbox_y < 0 && bbox_height > INT_MAX + bbox_y)
2476+
|| (bbox_y > 0 && bbox_height > INT_MAX - bbox_y)) {
2477+
return GD_FALSE;
2478+
}
2479+
bbox->x = bbox_x;
2480+
bbox->y = bbox_y;
2481+
bbox->width = bbox_width;
2482+
bbox->height = bbox_height;
24582483
return GD_TRUE;
24592484
}
24602485

ext/gd/tests/gh19730.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
GH-19730 (undefined behavior in gd_interpolation.c)
3+
--EXTENSIONS--
4+
gd
5+
--SKIPIF--
6+
<?php
7+
if (!GD_BUNDLED) {
8+
die("skip meaningful only for bundled libgd\n");
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
$im = imagecreatetruecolor(8, 8);
14+
$affine = [1211472000, 1, 1, 1, 1, 1];
15+
var_dump(imageaffine($im, $affine));
16+
?>
17+
--EXPECT--
18+
bool(false)

0 commit comments

Comments
 (0)