Skip to content

gdImageFillToBorder stack-overflow when invalid color is used #215

Closed
@fmunozs

Description

@fmunozs

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions