From f1b2afc9d9e77edf41804f5dfc4e2069d8a12975 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 16 Aug 2016 18:23:36 +0200 Subject: [PATCH 1/2] Fix #73868: DOS vulnerability in gdImageCreateFromGd2Ctx() We must not pretend that there are image data if there are none. Instead we fail reading the image file gracefully. (cherry picked from commit cdb648dc4115ce0722f3cc75e6a65115fc0e56ab) --- ext/gd/libgd/gd_gd2.c | 8 ++++++-- ext/gd/tests/bug73868.gd2 | Bin 0 -> 1050 bytes ext/gd/tests/bug73868.phpt | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 ext/gd/tests/bug73868.gd2 create mode 100644 ext/gd/tests/bug73868.phpt diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c index d06f328425e..196b7858dc4 100644 --- a/ext/gd/libgd/gd_gd2.c +++ b/ext/gd/libgd/gd_gd2.c @@ -340,12 +340,16 @@ gdImagePtr gdImageCreateFromGd2Ctx (gdIOCtxPtr in) for (x = xlo; x < xhi; x++) { if (im->trueColor) { if (!gdGetInt(&im->tpixels[y][x], in)) { - im->tpixels[y][x] = 0; + php_gd_error("gd2: EOF while reading\n"); + gdImageDestroy(im); + return NULL; } } else { int ch; if (!gdGetByte(&ch, in)) { - ch = 0; + php_gd_error("gd2: EOF while reading\n"); + gdImageDestroy(im); + return NULL; } im->pixels[y][x] = ch; } diff --git a/ext/gd/tests/bug73868.gd2 b/ext/gd/tests/bug73868.gd2 new file mode 100644 index 0000000000000000000000000000000000000000..1c797d1acfae114be5505962f9f3201f01bca420 GIT binary patch literal 1050 kcmYdKF=Aj~GB98;U@~A}1kqrw!6+CFfzc2c!6Cp30J@*U8UO$Q literal 0 HcmV?d00001 diff --git a/ext/gd/tests/bug73868.phpt b/ext/gd/tests/bug73868.phpt new file mode 100644 index 00000000000..135be7917b3 --- /dev/null +++ b/ext/gd/tests/bug73868.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug 73868 (DOS vulnerability in gdImageCreateFromGd2Ctx()) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +Warning: imagecreatefromgd2(): gd2: EOF while reading + in %s on line %d + +Warning: imagecreatefromgd2(): '%s' is not a valid GD2 file in %s on line %d +bool(false) +===DONE=== From d2274b01cbbadf5516b3ea87ad76fbae18834007 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 17 Dec 2016 17:06:58 +0100 Subject: [PATCH 2/2] Fix #73869: Signed Integer Overflow gd_io.c GD2 stores the number of horizontal and vertical chunks as words (i.e. 2 byte unsigned). These values are multiplied and assigned to an int when reading the image, what can cause integer overflows. We have to avoid that, and also make sure that either chunk count is actually greater than zero. If illegal chunk counts are detected, we bail out from reading the image. (cherry picked from commit 5b5d9db3988b829e0b121b74bb3947f01c2796a1) --- ext/gd/libgd/gd_gd2.c | 4 ++++ ext/gd/tests/bug73869.phpt | 19 +++++++++++++++++++ ext/gd/tests/bug73869a.gd2 | Bin 0 -> 92 bytes ext/gd/tests/bug73869b.gd2 | Bin 0 -> 18 bytes 4 files changed, 23 insertions(+) create mode 100644 ext/gd/tests/bug73869.phpt create mode 100644 ext/gd/tests/bug73869a.gd2 create mode 100644 ext/gd/tests/bug73869b.gd2 diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c index 196b7858dc4..3eba6b3054f 100644 --- a/ext/gd/libgd/gd_gd2.c +++ b/ext/gd/libgd/gd_gd2.c @@ -136,6 +136,10 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in GD2_DBG(php_gd_error("%d Chunks vertically", *ncy)); if (gd2_compressed(*fmt)) { + if (*ncx <= 0 || *ncy <= 0 || *ncx > INT_MAX / *ncy) { + GD2_DBG(printf ("Illegal chunk counts: %d * %d\n", *ncx, *ncy)); + goto fail1; + } nc = (*ncx) * (*ncy); GD2_DBG(php_gd_error("Reading %d chunk index entries", nc)); if (overflow2(sizeof(t_chunk_info), nc)) { diff --git a/ext/gd/tests/bug73869.phpt b/ext/gd/tests/bug73869.phpt new file mode 100644 index 00000000000..3cc10a42018 --- /dev/null +++ b/ext/gd/tests/bug73869.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #73869 (Signed Integer Overflow gd_io.c) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +Warning: imagecreatefromgd2(): '%s' is not a valid GD2 file in %s on line %d +bool(false) + +Warning: imagecreatefromgd2(): '%s' is not a valid GD2 file in %s on line %d +bool(false) +===DONE=== \ No newline at end of file diff --git a/ext/gd/tests/bug73869a.gd2 b/ext/gd/tests/bug73869a.gd2 new file mode 100644 index 0000000000000000000000000000000000000000..5060bfde3aad5687c0a962a8eddf86c0a83dded9 GIT binary patch literal 92 zcmYdKF=Aj~Vn_kP1_qY@zyAMbU|^63Vq3=lKu|H~?Lk9EAotLMul{dSxfcMLM1ThA IISver0HbRYrvLx| literal 0 HcmV?d00001 diff --git a/ext/gd/tests/bug73869b.gd2 b/ext/gd/tests/bug73869b.gd2 new file mode 100644 index 0000000000000000000000000000000000000000..8600126becb28c0962812c00fc6f2919b9f2ba80 GIT binary patch literal 18 VcmYdKF=Aj~G5`XG1`y4_001560-^u_ literal 0 HcmV?d00001