From 34c22f57dd95b2934c36f30087b0919fa2167f47 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jul 28 2020 10:29:57 +0000 Subject: import gd-2.2.5-7.el8 --- diff --git a/SOURCES/gd-2.2.5-null-pointer.patch b/SOURCES/gd-2.2.5-null-pointer.patch new file mode 100644 index 0000000..afa18d9 --- /dev/null +++ b/SOURCES/gd-2.2.5-null-pointer.patch @@ -0,0 +1,74 @@ +From a93eac0e843148dc2d631c3ba80af17e9c8c860f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?F=C3=A1bio=20Cabral=20Pacheco?= +Date: Fri, 20 Dec 2019 12:03:33 -0300 +Subject: [PATCH] Fix potential NULL pointer dereference in gdImageClone() + +--- + src/gd.c | 9 +-------- + tests/gdimageclone/style.c | 30 ++++++++++++++++++++++++++++++ + 5 files changed, 35 insertions(+), 9 deletions(-) + create mode 100644 tests/gdimageclone/style.c + +diff --git a/src/gd.c b/src/gd.c +index 592a0286..d564d1f9 100644 +--- a/src/gd.c ++++ b/src/gd.c +@@ -2865,14 +2865,6 @@ BGD_DECLARE(gdImagePtr) gdImageClone (gdImagePtr src) { + } + } + +- if (src->styleLength > 0) { +- dst->styleLength = src->styleLength; +- dst->stylePos = src->stylePos; +- for (i = 0; i < src->styleLength; i++) { +- dst->style[i] = src->style[i]; +- } +- } +- + dst->interlace = src->interlace; + + dst->alphaBlendingFlag = src->alphaBlendingFlag; +@@ -2907,6 +2899,7 @@ BGD_DECLARE(gdImagePtr) gdImageClone (gdImagePtr src) { + + if (src->style) { + gdImageSetStyle(dst, src->style, src->styleLength); ++ dst->stylePos = src->stylePos; + } + + for (i = 0; i < gdMaxColors; i++) { +diff --git a/tests/gdimageclone/style.c b/tests/gdimageclone/style.c +new file mode 100644 +index 00000000..c2b246ed +--- /dev/null ++++ b/tests/gdimageclone/style.c +@@ -0,0 +1,30 @@ ++/** ++ * Cloning an image should exactly reproduce all style related data ++ */ ++ ++ ++#include ++#include "gd.h" ++#include "gdtest.h" ++ ++ ++int main() ++{ ++ gdImagePtr im, clone; ++ int style[] = {0, 0, 0}; ++ ++ im = gdImageCreate(8, 8); ++ gdImageSetStyle(im, style, sizeof(style)/sizeof(style[0])); ++ ++ clone = gdImageClone(im); ++ gdTestAssert(clone != NULL); ++ ++ gdTestAssert(clone->styleLength == im->styleLength); ++ gdTestAssert(clone->stylePos == im->stylePos); ++ gdTestAssert(!memcmp(clone->style, im->style, sizeof(style)/sizeof(style[0]))); ++ ++ gdImageDestroy(clone); ++ gdImageDestroy(im); ++ ++ return gdNumFailures(); ++} diff --git a/SOURCES/gd-2.2.5-out-of-bounds-write-on-heap.patch b/SOURCES/gd-2.2.5-out-of-bounds-write-on-heap.patch new file mode 100644 index 0000000..0a3e7c7 --- /dev/null +++ b/SOURCES/gd-2.2.5-out-of-bounds-write-on-heap.patch @@ -0,0 +1,120 @@ +From 5b026e3cc05d7041cbe47a8702f1b51ffbf0a99b Mon Sep 17 00:00:00 2001 +From: Ondrej Dubaj +Date: Thu, 5 Mar 2020 11:02:27 +0100 +Subject: [PATCH] Imagecolormatch Out Of Bounds Write on Heap + +At least some of the image reading functions may return images which +use color indexes greater than or equal to im->colorsTotal. We cater +to this by always using a buffer size which is sufficient for +`gdMaxColors` in `gdImageColorMatch()`. + +Resolves: #1678104 +Version: 2.2.5-7 +--- + src/gd_color_match.c | 4 ++-- + tests/CMakeLists.txt | 1 + + tests/Makefile.am | 1 + + tests/gdimagecolormatch/CMakeLists.txt | 5 +++++ + tests/gdimagecolormatch/Makemodule.am | 5 +++++ + tests/gdimagecolormatch/cve_2019_6977.c | 25 +++++++++++++++++++++++++ + 6 files changed, 39 insertions(+), 2 deletions(-) + create mode 100644 tests/gdimagecolormatch/CMakeLists.txt + create mode 100644 tests/gdimagecolormatch/Makemodule.am + create mode 100644 tests/gdimagecolormatch/cve_2019_6977.c + +diff --git a/src/gd_color_match.c b/src/gd_color_match.c +index f0842b6..a94a841 100755 +--- a/src/gd_color_match.c ++++ b/src/gd_color_match.c +@@ -31,8 +31,8 @@ BGD_DECLARE(int) gdImageColorMatch (gdImagePtr im1, gdImagePtr im2) + return -4; /* At least 1 color must be allocated */ + } + +- buf = (unsigned long *)gdMalloc(sizeof(unsigned long) * 5 * im2->colorsTotal); +- memset (buf, 0, sizeof(unsigned long) * 5 * im2->colorsTotal ); ++ buf = (unsigned long *)gdMalloc(sizeof(unsigned long) * 5 * gdMaxColors); ++ memset (buf, 0, sizeof(unsigned long) * 5 * gdMaxColors ); + + for (x=0; x < im1->sx; x++) { + for( y=0; ysy; y++ ) { +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index 7eef4bf..6979416 100755 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -31,6 +31,7 @@ if (BUILD_TEST) + gdimagecolordeallocate + gdimagecolorexact + gdimagecolorreplace ++ gdimagecolormatch + gdimagecolorresolve + gdimagecolortransparent + gdimagecontrast +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 5f8b624..1a44112 100755 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -26,6 +26,7 @@ include gdimagecolorclosest/Makemodule.am + include gdimagecolordeallocate/Makemodule.am + include gdimagecolorexact/Makemodule.am + include gdimagecolorreplace/Makemodule.am ++include gdimagecolormatch/Makemodule.am + include gdimagecolorresolve/Makemodule.am + include gdimagecolortransparent/Makemodule.am + include gdimagecontrast/Makemodule.am +diff --git a/tests/gdimagecolormatch/CMakeLists.txt b/tests/gdimagecolormatch/CMakeLists.txt +new file mode 100644 +index 0000000..591938f +--- /dev/null ++++ b/tests/gdimagecolormatch/CMakeLists.txt +@@ -0,0 +1,5 @@ ++LIST(APPEND TESTS_FILES ++ cve_2019_6977 ++) ++ ++ADD_GD_TESTS() +diff --git a/tests/gdimagecolormatch/Makemodule.am b/tests/gdimagecolormatch/Makemodule.am +new file mode 100644 +index 0000000..e8e09a9 +--- /dev/null ++++ b/tests/gdimagecolormatch/Makemodule.am +@@ -0,0 +1,5 @@ ++libgd_test_programs += \ ++ gdimagecolormatch/cve_2019_6977 ++ ++EXTRA_DIST += \ ++ gdimagecolormatch/CMakeLists.txt +diff --git a/tests/gdimagecolormatch/cve_2019_6977.c b/tests/gdimagecolormatch/cve_2019_6977.c +new file mode 100644 +index 0000000..fdd7af5 +--- /dev/null ++++ b/tests/gdimagecolormatch/cve_2019_6977.c +@@ -0,0 +1,25 @@ ++/** ++ * Test for CVE-2019-6977 ++ */ ++ ++#include "gd.h" ++ ++int main() ++{ ++ gdImagePtr im1; ++ gdImagePtr im2; ++ ++ im1 = gdImageCreateTrueColor(0xfff, 0xfff); ++ im2 = gdImageCreate(0xfff, 0xfff); ++ if (gdImageColorAllocate(im2, 0, 0, 0) < 0) ++ { ++ gdImageDestroy(im1); ++ gdImageDestroy(im2); ++ return 1; ++ } ++ gdImageSetPixel(im2, 0, 0, 255); ++ gdImageColorMatch(im1, im2); ++ gdImageDestroy(im1); ++ gdImageDestroy(im2); ++ return 0; ++} +-- +2.24.1 + + diff --git a/SOURCES/gd-2.2.5-potential-double-free.patch b/SOURCES/gd-2.2.5-potential-double-free.patch new file mode 100644 index 0000000..ad6f54d --- /dev/null +++ b/SOURCES/gd-2.2.5-potential-double-free.patch @@ -0,0 +1,284 @@ +From d98e5a2ace46adcefa093c029663575fd677bf05 Mon Sep 17 00:00:00 2001 +From: Ondrej Dubaj +Date: Tue, 4 Jun 2019 13:05:57 +0200 +Subject: [PATCH] Potential double-free in gdImage*Ptr() + +Whenever `gdImage*Ptr()` calls `gdImage*Ctx()` and the latter fails, we +must not call `gdDPExtractData()`; otherwise a double-free would +happen. Since `gdImage*Ctx()` are void functions, and we can't change +that for BC reasons, we're introducing static helpers which are used +internally. + +We're adding a regression test for `gdImageJpegPtr()`, but not for +`gdImageGifPtr()` and `gdImageWbmpPtr()` since we don't know how to +trigger failure of the respective `gdImage*Ctx()` calls. + +This potential security issue has been reported by Solmaz Salimi (aka. +Rooney). +--- + src/gd_gif_out.c | 19 +++++++++++++++---- + src/gd_jpeg.c | 20 ++++++++++++++++---- + src/gd_wbmp.c | 21 ++++++++++++++++++--- + tests/jpeg/CMakeLists.txt | 1 + + tests/jpeg/Makemodule.am | 3 ++- + tests/jpeg/jpeg_ptr_double_free.c | 31 +++++++++++++++++++++++++++++++ + 6 files changed, 83 insertions(+), 12 deletions(-) + create mode 100644 tests/jpeg/jpeg_ptr_double_free.c + +diff --git a/src/gd_gif_out.c b/src/gd_gif_out.c +index 6fe707d..4a05c09 100755 +--- a/src/gd_gif_out.c ++++ b/src/gd_gif_out.c +@@ -99,7 +99,7 @@ static void char_init(GifCtx *ctx); + static void char_out(int c, GifCtx *ctx); + static void flush_char(GifCtx *ctx); + +- ++static int _gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out); + + + /* +@@ -131,8 +131,11 @@ BGD_DECLARE(void *) gdImageGifPtr(gdImagePtr im, int *size) + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + if (out == NULL) return NULL; +- gdImageGifCtx(im, out); +- rv = gdDPExtractData(out, size); ++ if (!_gdImageGifCtx(im, out)) { ++ rv = gdDPExtractData(out, size); ++ } else { ++ rv = NULL; ++ } + out->gd_free(out); + return rv; + } +@@ -220,6 +223,12 @@ BGD_DECLARE(void) gdImageGif(gdImagePtr im, FILE *outFile) + + */ + BGD_DECLARE(void) gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out) ++{ ++ _gdImageGifCtx(im, out); ++} ++ ++/* returns 0 on success, 1 on failure */ ++static int _gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out) + { + gdImagePtr pim = 0, tim = im; + int interlace, BitsPerPixel; +@@ -231,7 +240,7 @@ BGD_DECLARE(void) gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out) + based temporary image. */ + pim = gdImageCreatePaletteFromTrueColor(im, 1, 256); + if(!pim) { +- return; ++ return 1; + } + tim = pim; + } +@@ -247,6 +256,8 @@ BGD_DECLARE(void) gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out) + /* Destroy palette based temporary image. */ + gdImageDestroy( pim); + } ++ ++ return 0; + } + + +diff --git a/src/gd_jpeg.c b/src/gd_jpeg.c +index 271ef46..bd8fc27 100755 +--- a/src/gd_jpeg.c ++++ b/src/gd_jpeg.c +@@ -123,6 +123,8 @@ static void fatal_jpeg_error(j_common_ptr cinfo) + exit(99); + } + ++static int _gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality); ++ + /* + * Write IM to OUTFILE as a JFIF-formatted JPEG image, using quality + * QUALITY. If QUALITY is in the range 0-100, increasing values +@@ -237,8 +239,11 @@ BGD_DECLARE(void *) gdImageJpegPtr(gdImagePtr im, int *size, int quality) + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + if (out == NULL) return NULL; +- gdImageJpegCtx(im, out, quality); +- rv = gdDPExtractData(out, size); ++ if (!_gdImageJpegCtx(im, out, quality)) { ++ rv = gdDPExtractData(out, size); ++ } else { ++ rv = NULL; ++ } + out->gd_free(out); + return rv; + } +@@ -259,6 +264,12 @@ void jpeg_gdIOCtx_dest(j_compress_ptr cinfo, gdIOCtx *outfile); + + */ + BGD_DECLARE(void) gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality) ++{ ++ _gdImageJpegCtx(im, outfile, quality); ++} ++ ++/* returns 0 on success, 1 on failure */ ++static int _gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality) + { + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; +@@ -293,7 +304,7 @@ BGD_DECLARE(void) gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality) + if(row) { + gdFree(row); + } +- return; ++ return 1; + } + + cinfo.err->emit_message = jpeg_emit_message; +@@ -334,7 +345,7 @@ BGD_DECLARE(void) gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality) + if(row == 0) { + gd_error("gd-jpeg: error: unable to allocate JPEG row structure: gdCalloc returns NULL\n"); + jpeg_destroy_compress(&cinfo); +- return; ++ return 1; + } + + rowptr[0] = row; +@@ -411,6 +422,7 @@ BGD_DECLARE(void) gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality) + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + gdFree(row); ++ return 0; + } + + +diff --git a/src/gd_wbmp.c b/src/gd_wbmp.c +index 0028273..341ff6e 100755 +--- a/src/gd_wbmp.c ++++ b/src/gd_wbmp.c +@@ -88,6 +88,8 @@ int gd_getin(void *in) + return (gdGetC((gdIOCtx *)in)); + } + ++static int _gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out); ++ + /* + Function: gdImageWBMPCtx + +@@ -100,6 +102,12 @@ int gd_getin(void *in) + out - the stream where to write + */ + BGD_DECLARE(void) gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out) ++{ ++ _gdImageWBMPCtx(image, fg, out); ++} ++ ++/* returns 0 on success, 1 on failure */ ++static int _gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out) + { + int x, y, pos; + Wbmp *wbmp; +@@ -107,7 +115,7 @@ BGD_DECLARE(void) gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out) + /* create the WBMP */ + if((wbmp = createwbmp(gdImageSX(image), gdImageSY(image), WBMP_WHITE)) == NULL) { + gd_error("Could not create WBMP\n"); +- return; ++ return 1; + } + + /* fill up the WBMP structure */ +@@ -123,11 +131,15 @@ BGD_DECLARE(void) gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out) + + /* write the WBMP to a gd file descriptor */ + if(writewbmp(wbmp, &gd_putout, out)) { ++ freewbmp(wbmp); + gd_error("Could not save WBMP\n"); ++ return 1; + } + + /* des submitted this bugfix: gdFree the memory. */ + freewbmp(wbmp); ++ ++ return 0; + } + + /* +@@ -271,8 +283,11 @@ BGD_DECLARE(void *) gdImageWBMPPtr(gdImagePtr im, int *size, int fg) + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + if (out == NULL) return NULL; +- gdImageWBMPCtx(im, fg, out); +- rv = gdDPExtractData(out, size); ++ if (!_gdImageWBMPCtx(im, fg, out)) { ++ rv = gdDPExtractData(out, size); ++ } else { ++ rv = NULL; ++ } + out->gd_free(out); + return rv; + } +diff --git a/tests/jpeg/CMakeLists.txt b/tests/jpeg/CMakeLists.txt +index 19964b0..a8d8162 100755 +--- a/tests/jpeg/CMakeLists.txt ++++ b/tests/jpeg/CMakeLists.txt +@@ -2,6 +2,7 @@ IF(JPEG_FOUND) + LIST(APPEND TESTS_FILES + jpeg_empty_file + jpeg_im2im ++ jpeg_ptr_double_free + jpeg_null + ) + +diff --git a/tests/jpeg/Makemodule.am b/tests/jpeg/Makemodule.am +index 7e5d317..b89e169 100755 +--- a/tests/jpeg/Makemodule.am ++++ b/tests/jpeg/Makemodule.am +@@ -2,7 +2,8 @@ if HAVE_LIBJPEG + libgd_test_programs += \ + jpeg/jpeg_empty_file \ + jpeg/jpeg_im2im \ +- jpeg/jpeg_null ++ jpeg/jpeg_null \ ++ jpeg/jpeg_ptr_double_free + + if HAVE_LIBPNG + libgd_test_programs += \ +diff --git a/tests/jpeg/jpeg_ptr_double_free.c b/tests/jpeg/jpeg_ptr_double_free.c +new file mode 100644 +index 0000000..c80aeb6 +--- /dev/null ++++ b/tests/jpeg/jpeg_ptr_double_free.c +@@ -0,0 +1,31 @@ ++/** ++ * Test that failure to convert to JPEG returns NULL ++ * ++ * We are creating an image, set its width to zero, and pass this image to ++ * `gdImageJpegPtr()` which is supposed to fail, and as such should return NULL. ++ * ++ * See also ++ */ ++ ++ ++#include "gd.h" ++#include "gdtest.h" ++ ++ ++int main() ++{ ++ gdImagePtr src, dst; ++ int size; ++ ++ src = gdImageCreateTrueColor(1, 10); ++ gdTestAssert(src != NULL); ++ ++ src->sx = 0; /* this hack forces gdImageJpegPtr() to fail */ ++ ++ dst = gdImageJpegPtr(src, &size, 0); ++ gdTestAssert(dst == NULL); ++ ++ gdImageDestroy(src); ++ ++ return gdNumFailures(); ++} +\ No newline at end of file +-- +2.17.1 + + diff --git a/SPECS/gd.spec b/SPECS/gd.spec index 4b54a55..bfc6fc8 100644 --- a/SPECS/gd.spec +++ b/SPECS/gd.spec @@ -9,7 +9,7 @@ Summary: A graphics library for quick creation of PNG or JPEG images Name: gd Version: 2.2.5 -Release: 6%{?prever}%{?short}%{?dist} +Release: 7%{?prever}%{?short}%{?dist} Group: System Environment/Libraries License: MIT URL: http://libgd.github.io/ @@ -26,6 +26,13 @@ Patch1: gd-2.1.0-multilib.patch Patch2: gd-2.2.5-upstream.patch # CVE-2018-1000222 - https://github.com/libgd/libgd/commit/ac16bdf2d41724b5a65255d4c28fb0ec46bc42f5 Patch3: gd-2.2.5-gdImageBmpPtr-double-free.patch +# CVE-2019-6977 +Patch4: gd-2.2.5-out-of-bounds-write-on-heap.patch +# CVE-2019-6978 +Patch5: gd-2.2.5-potential-double-free.patch +# CVE-2018-14553 - https://github.com/fcabralpacheco/libgd/commit/441cbfed60ebf6cb63b8ce120ed0a82b15e7aaf8 +Patch6: gd-2.2.5-null-pointer.patch + BuildRequires: freetype-devel BuildRequires: fontconfig-devel @@ -91,6 +98,9 @@ files for gd, a graphics library for creating PNG and JPEG graphics. %patch1 -p1 -b .mlib %patch2 -p1 -b .upstream %patch3 -p1 -b .gdImageBmpPtr-free +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 : $(perl config/getver.pl) @@ -166,6 +176,15 @@ grep %{version} $RPM_BUILD_ROOT%{_libdir}/pkgconfig/gdlib.pc %changelog + +* Fri Mar 27 2020 fjanus@redhat.com - 2.2.5-7 +- Fix CVE-2018-14553 - Potential Null pointer dereference in gdImageClone + Resolves: RHBZ#1811788 +- Fixed heap based buffer overflow in gd_color_match.c:gdImageColorMatch() in libgd as used in imagecolormatch() + Resolves: RHBZ#1678104 (CVE-2019-6977) +- Fixed potential double-free in gdImage*Ptr() + Resolves: RHBZ#1679002 (CVE-2019-6978) + * Mon Sep 10 2018 mskalick@redhat.com - 2.2.5-6 - Check return value in gdImageBmpPtr to avoid double free (CVE-2018-1000222) Resolves: RHBZ#1621956