From 5fa4e6f6e7b09269ec6224a155707dce47b03c0f Mon Sep 17 00:00:00 2001 From: Jan Oravec Date: Mon, 15 Aug 2016 13:17:58 -0700 Subject: [PATCH] Fix some color related crashes in libgd Summary: Various paths use the color as an index into a 256 element table without checking it, and passing -7 as a color to imageline would unconditionally cause it to treat the image as truecolor, seg-faulting if it wasn't. Reviewed By: alexmalyshev Differential Revision: D3658241 fbshipit-source-id: 0f4a9f32dce0a733b5749451b239badd0bfc4d49 --- hphp/runtime/ext/gd/ext_gd.cpp | 5 ++--- hphp/runtime/ext/gd/libgd/gd.cpp | 8 ++++++++ hphp/runtime/ext/gd/libgd/gd_crop.cpp | 4 ++++ hphp/runtime/ext/gd/libgd/gd_gd2.cpp | 4 +++- hphp/runtime/ext/gd/libgd/gd_topal.cpp | 4 ++++ hphp/test/slow/ext_gd/colorcrash.php | 8 ++++++++ hphp/test/slow/ext_gd/colorcrash.php.expect | 1 + 7 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 hphp/test/slow/ext_gd/colorcrash.php create mode 100644 hphp/test/slow/ext_gd/colorcrash.php.expect diff --git a/hphp/runtime/ext/gd/ext_gd.cpp b/hphp/runtime/ext/gd/ext_gd.cpp index 7f64acab7377f9..c94b031fe95cc3 100644 --- a/hphp/runtime/ext/gd/ext_gd.cpp +++ b/hphp/runtime/ext/gd/ext_gd.cpp @@ -3891,9 +3891,8 @@ Variant HHVM_FUNCTION(imagecolorsforindex, const Resource& image, int64_t index) { gdImagePtr im = get_valid_image_resource(image); if (!im) return false; - if ((index >= 0 && gdImageTrueColor(im)) || - (!gdImageTrueColor(im) && index >= 0 && - index < gdImageColorsTotal(im))) { + if (index >= 0 && + (gdImageTrueColor(im) || index < gdImageColorsTotal(im))) { return make_map_array( s_red, gdImageRed(im,index), s_green, gdImageGreen(im,index), diff --git a/hphp/runtime/ext/gd/libgd/gd.cpp b/hphp/runtime/ext/gd/libgd/gd.cpp index 18fa73ae6965d5..0a2bb48b1a2d03 100644 --- a/hphp/runtime/ext/gd/libgd/gd.cpp +++ b/hphp/runtime/ext/gd/libgd/gd.cpp @@ -1011,6 +1011,12 @@ void gdImageAABlend (gdImagePtr im) int p_color, p_red, p_green, p_blue; int px, py; + if (!gdImageTrueColor(im) && color >= gdImageColorsTotal(im)) { + color = gdImageColorsTotal(im) - 1; + } + if (color < 0) { + color = 0; + } color_red = gdImageRed(im, color); color_green = gdImageGreen(im, color); color_blue = gdImageBlue(im, color); @@ -1284,6 +1290,8 @@ inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color **/ void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col) { + if (!gdImageTrueColor(im)) return; + /* keep them as 32bits */ long x, y, inc; long dx, dy,tmp; diff --git a/hphp/runtime/ext/gd/libgd/gd_crop.cpp b/hphp/runtime/ext/gd/libgd/gd_crop.cpp index 34c712e668ad8f..9fff7e233fd7f8 100644 --- a/hphp/runtime/ext/gd/libgd/gd_crop.cpp +++ b/hphp/runtime/ext/gd/libgd/gd_crop.cpp @@ -238,6 +238,10 @@ gdImagePtr gdImageCropThreshold(gdImagePtr im, const unsigned int color, return nullptr; } + if (!gdImageTrueColor(im) && color > gdImageColorsTotal(im)) { + return nullptr; + } + /* TODO: Add gdImageGetRowPtr and works with ptr at the row level * for the true color and palette images * new formats will simply work with ptr diff --git a/hphp/runtime/ext/gd/libgd/gd_gd2.cpp b/hphp/runtime/ext/gd/libgd/gd_gd2.cpp index 7435667d31529b..94b827eae7b490 100644 --- a/hphp/runtime/ext/gd/libgd/gd_gd2.cpp +++ b/hphp/runtime/ext/gd/libgd/gd_gd2.cpp @@ -666,10 +666,12 @@ static void _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) /* Force fmt to a valid value since we don't return anything. */ if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) { - fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED : GD2_FMT_COMPRESSED; + fmt = GD2_FMT_COMPRESSED; } if (im->trueColor) { fmt += 2; + assert(fmt == GD2_FMT_TRUECOLOR_RAW || + fmt == GD2_FMT_TRUECOLOR_COMPRESSED); } /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems * a little silly to expect performance improvements on a 64x64 bit scale, and diff --git a/hphp/runtime/ext/gd/libgd/gd_topal.cpp b/hphp/runtime/ext/gd/libgd/gd_topal.cpp index 9354ce46897b70..b9cd0243930d1e 100644 --- a/hphp/runtime/ext/gd/libgd/gd_topal.cpp +++ b/hphp/runtime/ext/gd/libgd/gd_topal.cpp @@ -1818,6 +1818,10 @@ static void gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int color { colorsWanted = maxColors; } + if (colorsWanted <= 0) { + colorsWanted = 1; + } + if (!cimP) { nim->pixels = (unsigned char **) gdCalloc (sizeof (unsigned char *), oim->sy); if (!nim->pixels) diff --git a/hphp/test/slow/ext_gd/colorcrash.php b/hphp/test/slow/ext_gd/colorcrash.php new file mode 100644 index 00000000000000..dfc9aaa532a3c0 --- /dev/null +++ b/hphp/test/slow/ext_gd/colorcrash.php @@ -0,0 +1,8 @@ +