{"action":"created","issue":{"url":"https://api.github.com/repos/libgd/libgd/issues/215","repository_url":"https://api.github.com/repos/libgd/libgd","labels_url":"https://api.github.com/repos/libgd/libgd/issues/215/labels{/name}","comments_url":"https://api.github.com/repos/libgd/libgd/issues/215/comments","events_url":"https://api.github.com/repos/libgd/libgd/issues/215/events","html_url":"https://github.com/libgd/libgd/issues/215","id":156723764,"number":215,"title":"gdImageFillToBorder stack-overflow when invalid color is used","user":{"login":"fmunozs","id":1041604,"avatar_url":"https://avatars.githubusercontent.com/u/1041604?v=3","gravatar_id":"","url":"https://api.github.com/users/fmunozs","html_url":"https://github.com/fmunozs","followers_url":"https://api.github.com/users/fmunozs/followers","following_url":"https://api.github.com/users/fmunozs/following{/other_user}","gists_url":"https://api.github.com/users/fmunozs/gists{/gist_id}","starred_url":"https://api.github.com/users/fmunozs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fmunozs/subscriptions","organizations_url":"https://api.github.com/users/fmunozs/orgs","repos_url":"https://api.github.com/users/fmunozs/repos","events_url":"https://api.github.com/users/fmunozs/events{/privacy}","received_events_url":"https://api.github.com/users/fmunozs/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/libgd/libgd/labels/bug","name":"bug","color":"fc2929"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2016-05-25T11:11:05Z","updated_at":"2016-06-02T11:51:16Z","closed_at":null,"body":"Invalid color causes stack exhaustion by recursive call to function gdImageFillToBorder when the image used is not truecolor.\r\n\r\nSource code:\r\nhttps://github.com/php/php-src/blob/master/ext/gd/libgd/gd.c#L1811\r\n\r\n```\r\n    if (y > 0) {\r\n        lastBorder = 1;\r\n        for (i = leftLimit; i <= rightLimit; i++) {\r\n            int c = gdImageGetPixel(im, i, y - 1);\r\n            if (lastBorder) {\r\n                if ((c != border) && (c != color)) {\r\n                    gdImageFillToBorder(im, i, y - 1, border, color);\r\n                    lastBorder = 0;\r\n                }\r\n            } else if ((c == border) || (c == color)) {\r\n                lastBorder = 1;\r\n            }\r\n        }\r\n    }\r\n\r\n    /* Below */\r\n    if (y < ((im->sy) - 1)) {\r\n        lastBorder = 1;\r\n        for (i = leftLimit; i <= rightLimit; i++) {\r\n            int c = gdImageGetPixel(im, i, y + 1);\r\n\r\n            if (lastBorder) {\r\n                if ((c != border) && (c != color)) {\r\n                    gdImageFillToBorder(im, i, y + 1, border, color);\r\n                    lastBorder = 0;\r\n                }\r\n            } else if ((c == border) || (c == color)) {\r\n                lastBorder = 1;\r\n            }\r\n        }\r\n    }\r\n    im->alphaBlendingFlag = restoreAlphaBlending;\r\n```\r\n\r\n-------------------------------------\r\n\r\n```\r\ngdb -q --args /home/user/php-7.0/sapi/cli/php -n poc.php\r\nReading symbols from /home/user/php-7.0/sapi/cli/php...done.\r\n(gdb) b gd.c:1811\r\nBreakpoint 1 at 0x8176146: file /home/user/php-7.0/ext/gd/libgd/gd.c, line 1811.\r\n(gdb) b gd.c:1829\r\nBreakpoint 2 at 0x81761f2: file /home/user/php-7.0/ext/gd/libgd/gd.c, line 1829.\r\n(gdb) r\r\nStarting program: /home/user/php-7.0/sapi/cli/php -n poc.php\r\n\r\nBreakpoint 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\r\n1829                                            gdImageFillToBorder(im, i, y + 1, border, color);\r\n(gdb) p c\r\n$1 = 0\r\n(gdb) c\r\nContinuing.\r\n\r\nBreakpoint 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\r\n1811                                    if ((c != border) && (c != color)) {\r\n(gdb) p c\r\n$2 = 57         (different of color 313)\r\n(gdb) c\r\nContinuing.\r\n\r\nBreakpoint 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\r\n1829                                            gdImageFillToBorder(im, i, y + 1, border, color);\r\n(gdb) p c\r\n$3 = 57        (different of color 313)\r\n(gdb) c\r\nContinuing.\r\n\r\nBreakpoint 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\r\n1811                                    if ((c != border) && (c != color)) {\r\n(gdb) p c\r\n$4 = 57        (different of color 313)\r\n```\r\nTest script:\r\n---------------\r\n```\r\n<?php\r\n$img = imagecreate(10, 10);\r\nimagefilltoborder($img, 0, 0, 1, 0x139);\r\n```\r\n\r\nExpected result:\r\n----------------\r\nNo crash\r\n\r\nActual result:\r\n--------------\r\n```\r\nuser@Xenial32-2:~/crashes/fillborder$ /ramdisk/php-71/sapi/cli/php -n poc.php\r\nASAN:SIGSEGV\r\n=================================================================\r\n==5027==ERROR: AddressSanitizer: stack-overflow on address 0xff276ff0 (pc 0x085ee3f8 bp 0x1e4cdb90 sp 0xff276ff0 T0)\r\n    #0 0x85ee3f7 in php_gd_gdImageSetPixel /home/user/php-7.1asan/ext/gd/libgd/gd.c:755\r\n    #1 0xf266bfff  (<unknown module>)\r\n\r\nSUMMARY: AddressSanitizer: stack-overflow /home/user/php-7.1asan/ext/gd/libgd/gd.c:755 php_gd_gdImageSetPixel\r\n==5027==ABORTING\r\nuser@Xenial32-2:~/crashes/fillborder$ /ramdisk/php-71/sapi/cli/php -n poc.php\r\nASAN:SIGSEGV\r\n=================================================================\r\n==5771==ERROR: AddressSanitizer: stack-overflow on address 0xff758ff4 (pc 0x085ebfcf bp 0xfffffffc sp 0xff758ff0 T0)\r\n    #0 0x85ebfce in gdImageTileApply /home/user/php-7.1asan/ext/gd/libgd/gd.c:869\r\n    #1 0x85ebfce in php_gd_gdImageSetPixel /home/user/php-7.1asan/ext/gd/libgd/gd.c:749\r\n    #2 0x85f7eae in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1788\r\n    #3 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829\r\n    #4 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812\r\n    #5 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829\r\n    #6 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812\r\n    #7 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829\r\n    #8 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812\r\n    #9 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829\r\n    #10 0x85f8e04 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1812\r\n    #11 0x85f8f32 in php_gd_gdImageFillToBorder /home/user/php-7.1asan/ext/gd/libgd/gd.c:1829\r\n```"},"comment":{"url":"https://api.github.com/repos/libgd/libgd/issues/comments/223269170","html_url":"https://github.com/libgd/libgd/issues/215#issuecomment-223269170","issue_url":"https://api.github.com/repos/libgd/libgd/issues/215","id":223269170,"user":{"login":"pierrejoye","id":282408,"avatar_url":"https://avatars.githubusercontent.com/u/282408?v=3","gravatar_id":"","url":"https://api.github.com/users/pierrejoye","html_url":"https://github.com/pierrejoye","followers_url":"https://api.github.com/users/pierrejoye/followers","following_url":"https://api.github.com/users/pierrejoye/following{/other_user}","gists_url":"https://api.github.com/users/pierrejoye/gists{/gist_id}","starred_url":"https://api.github.com/users/pierrejoye/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pierrejoye/subscriptions","organizations_url":"https://api.github.com/users/pierrejoye/orgs","repos_url":"https://api.github.com/users/pierrejoye/repos","events_url":"https://api.github.com/users/pierrejoye/events{/privacy}","received_events_url":"https://api.github.com/users/pierrejoye/received_events","type":"User","site_admin":false},"created_at":"2016-06-02T11:51:16Z","updated_at":"2016-06-02T11:51:16Z","body":"@vapier totally agree, sadly remaining of the old APIs where we try to keep BC.\r\n\r\nalso correct fix could be:\r\n\r\n\r\n\tif (!im->trueColor) {\r\n\t\tif (color >= gdMaxColors) && (color > im->colorsTotal)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\r\n\r\n"}}
{"actor":{"display_login":"pierrejoye"}}