Closed
Description
Invalid color causes stack exhaustion by recursive call to function gdImageFillToBorder when the image used is not truecolor.
Source code:
https://github.com/php/php-src/blob/master/ext/gd/libgd/gd.c#L1811
if (y > 0) {
lastBorder = 1;
for (i = leftLimit; i <= rightLimit; i++) {
int c = gdImageGetPixel(im, i, y - 1);
if (lastBorder) {
if ((c != border) && (c != color)) {
gdImageFillToBorder(im, i, y - 1, border, color);
lastBorder = 0;
}
} else if ((c == border) || (c == color)) {
lastBorder = 1;
}
}
}
/* Below */
if (y < ((im->sy) - 1)) {
lastBorder = 1;
for (i = leftLimit; i <= rightLimit; i++) {
int c = gdImageGetPixel(im, i, y + 1);
if (lastBorder) {
if ((c != border) && (c != color)) {
gdImageFillToBorder(im, i, y + 1, border, color);
lastBorder = 0;
}
} else if ((c == border) || (c == color)) {
lastBorder = 1;
}
}
}
im->alphaBlendingFlag = restoreAlphaBlending;
gdb -q --args /home/user/php-7.0/sapi/cli/php -n poc.php
Reading symbols from /home/user/php-7.0/sapi/cli/php...done.
(gdb) b gd.c:1811
Breakpoint 1 at 0x8176146: file /home/user/php-7.0/ext/gd/libgd/gd.c, line 1811.
(gdb) b gd.c:1829
Breakpoint 2 at 0x81761f2: file /home/user/php-7.0/ext/gd/libgd/gd.c, line 1829.
(gdb) r
Starting program: /home/user/php-7.0/sapi/cli/php -n poc.php
Breakpoint 2, php_gd_gdImageFillToBorder (im=0xf5a6c000, x=0, y=0, border=1, color=313) at /home/user/php-7.0/ext/gd/libgd/gd.c:1829
1829 gdImageFillToBorder(im, i, y + 1, border, color);
(gdb) p c
$1 = 0
(gdb) c
Continuing.
Breakpoint 1, php_gd_gdImageFillToBorder (im=0xf5a6c000, x=0, y=1, border=1, color=313) at /home/user/php-7.0/ext/gd/libgd/gd.c:1811
1811 if ((c != border) && (c != color)) {
(gdb) p c
$2 = 57 (different of color 313)
(gdb) c
Continuing.
Breakpoint 2, php_gd_gdImageFillToBorder (im=0xf5a6c000, x=0, y=0, border=1, color=313) at /home/user/php-7.0/ext/gd/libgd/gd.c:1829
1829 gdImageFillToBorder(im, i, y + 1, border, color);
(gdb) p c
$3 = 57 (different of color 313)
(gdb) c
Continuing.
Breakpoint 1, php_gd_gdImageFillToBorder (im=0xf5a6c000, x=0, y=1, border=1, color=313) at /home/user/php-7.0/ext/gd/libgd/gd.c:1811
1811 if ((c != border) && (c != color)) {
(gdb) p c
$4 = 57 (different of color 313)
Test script:
<?php
$img = imagecreate(10, 10);
imagefilltoborder($img, 0, 0, 1, 0x139);
Expected result:
No crash
Actual result:
user@Xenial32-2:~/crashes/fillborder$ /ramdisk/php-71/sapi/cli/php -n poc.php
ASAN:SIGSEGV
=================================================================
==5027==ERROR: AddressSanitizer: stack-overflow on address 0xff276ff0 (pc 0x085ee3f8 bp 0x1e4cdb90 sp 0xff276ff0 T0)
#0 0x85ee3f7 in php_gd_gdImageSetPixel /home/user/php-7.1asan/ext/gd/libgd/gd.c:755
#1 0xf266bfff (<unknown module>)
SUMMARY: AddressSanitizer: stack-overflow /home/user/php-7.1asan/ext/gd/libgd/gd.c:755 php_gd_gdImageSetPixel
==5027==ABORTING
user@Xenial32-2:~/crashes/fillborder$ /ramdisk/php-71/sapi/cli/php -n poc.php
ASAN:SIGSEGV
=================================================================
==5771==ERROR: AddressSanitizer: stack-overflow on address 0xff758ff4 (pc 0x085ebfcf bp 0xfffffffc sp 0xff758ff0 T0)
#0 0x85ebfce in gdImageTileApply /home/user/php-7.1asan/ext/gd/libgd/gd.c:869
#1 0x85ebfce in php_gd_gdImageSetPixel /home/user/php-7.1asan/ext/gd/libgd/gd.c:749
#2 0x85f7eae in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1788
#3 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829
#4 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812
#5 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829
#6 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812
#7 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829
#8 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812
#9 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829
#10 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812
#11 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829