From a11f47475e6443b7f32d21f2271f28f417e2ac04 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 29 Nov 2017 19:37:38 +0100 Subject: [PATCH] Fix #420: Potential infinite loop in gdImageCreateFromGifCtx Due to a signedness confusion in `GetCode_` a corrupt GIF file can trigger an infinite loop. Furthermore we make sure that a GIF without any palette entries is treated as invalid *after* open palette entries have been removed. CVE-2018-5711 See also https://bugs.php.net/bug.php?id=75571. --- src/gd_gif_in.c | 12 ++++++------ tests/gif/CMakeLists.txt | 1 + tests/gif/Makemodule.am | 2 ++ tests/gif/php_bug_75571.c | 28 ++++++++++++++++++++++++++++ tests/gif/php_bug_75571.gif | Bin 0 -> 1731 bytes 6 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 tests/gif/php_bug_75571.c diff --git a/src/gd_gif_in.c b/src/gd_gif_in.c index daf26e79..0a8bd717 100644 --- a/src/gd_gif_in.c +++ b/src/gd_gif_in.c @@ -335,11 +335,6 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd) return 0; } - if(!im->colorsTotal) { - gdImageDestroy(im); - return 0; - } - /* Check for open colors at the end, so * we can reduce colorsTotal and ultimately * BitsPerPixel */ @@ -351,6 +346,11 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd) } } + if(!im->colorsTotal) { + gdImageDestroy(im); + return 0; + } + return im; } @@ -447,7 +447,7 @@ static int GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP) { int i, j, ret; - unsigned char count; + int count; if(flag) { scd->curbit = 0; diff --git a/tests/gif/CMakeLists.txt b/tests/gif/CMakeLists.txt index 2b73749e..e58e6b09 100644 --- a/tests/gif/CMakeLists.txt +++ b/tests/gif/CMakeLists.txt @@ -4,6 +4,7 @@ LIST(APPEND TESTS_FILES bug00227 gif_null ossfuzz5700 + php_bug_75571 uninitialized_memory_read ) diff --git a/tests/gif/Makemodule.am b/tests/gif/Makemodule.am index 3199438f..5dbeac53 100644 --- a/tests/gif/Makemodule.am +++ b/tests/gif/Makemodule.am @@ -4,6 +4,7 @@ libgd_test_programs += \ gif/bug00227 \ gif/gif_null \ gif/ossfuzz5700 \ + gif/php_bug_75571 \ gif/uninitialized_memory_read if HAVE_LIBPNG @@ -26,4 +27,5 @@ EXTRA_DIST += \ gif/bug00066.gif \ gif/bug00066_exp.png \ gif/ossfuzz5700.gif \ + gif/php_bug_75571.gif \ gif/unitialized_memory_read.gif diff --git a/tests/gif/php_bug_75571.c b/tests/gif/php_bug_75571.c new file mode 100644 index 00000000..d4fae3ae --- /dev/null +++ b/tests/gif/php_bug_75571.c @@ -0,0 +1,28 @@ +/** + * Test that GIF reading does not loop infinitely + * + * We are reading a crafted GIF image which has been truncated. This would + * trigger an infinite loop formerly, but know bails out early, returning + * NULL from gdImageCreateFromGif(). + * + * See also https://bugs.php.net/bug.php?id=75571. + */ + + +#include "gd.h" +#include "gdtest.h" + + +int main() +{ + gdImagePtr im; + FILE *fp; + + fp = gdTestFileOpen2("gif", "php_bug_75571.gif"); + gdTestAssert(fp != NULL); + im = gdImageCreateFromGif(fp); + gdTestAssert(im == NULL); + fclose(fp); + + return gdNumFailures(); +}