Skip to content

Commit e45f5f6

Browse files
committed
Fix GH-22121: double-free in gdImageSetStyle() after overflow early return
gdImageSetStyle freed im->style before checking overflow2(). When the overflow check tripped and the function early-returned, im->style was left dangling. The next gdImageSetStyle, gdImageDestroy, or gdImageSetPixel gdStyled/gdStyledBrushed dispatch then freed or dereferenced it. Move the overflow check above the free to match upstream libgd (libgd/libgd src/gd.c::gdImageSetStyle), which has always had the check first. The original divergence was an oversight in 77ba248 when the overflow check was ported from libgd 2.0.29. Fixes GH-22121
1 parent c56f5ad commit e45f5f6

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

ext/gd/libgd/gd.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2879,12 +2879,12 @@ void gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
28792879

28802880
void gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
28812881
{
2882-
if (im->style) {
2883-
gdFree(im->style);
2884-
}
28852882
if (overflow2(sizeof (int), noOfPixels)) {
28862883
return;
28872884
}
2885+
if (im->style) {
2886+
gdFree(im->style);
2887+
}
28882888
im->style = (int *) gdMalloc(sizeof(int) * noOfPixels);
28892889
memcpy(im->style, style, sizeof(int) * noOfPixels);
28902890
im->styleLength = noOfPixels;

ext/gd/tests/gh22121.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-22121 (Double free in gdImageSetStyle() after overflow-triggered early return)
3+
--EXTENSIONS--
4+
gd
5+
--INI--
6+
memory_limit=-1
7+
--SKIPIF--
8+
<?php
9+
if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
10+
if (PHP_INT_SIZE < 8) die('skip 64-bit only (allocates ~10 GiB)');
11+
?>
12+
--FILE--
13+
<?php
14+
$im = imagecreatetruecolor(1, 1);
15+
imagesetstyle($im, [0]);
16+
imagesetstyle($im, array_fill(0, 536870912, 0));
17+
unset($im);
18+
echo "no double free\n";
19+
?>
20+
--EXPECTF--
21+
Warning: imagesetstyle(): Product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully
22+
in %s on line %d
23+
no double free

0 commit comments

Comments
 (0)