From 3dd0e308cbd2c24fde2fc9e9b707181252a2de95 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 5 May 2020 12:02:45 +0200 Subject: [PATCH] Fix #615: gdImageStringFT() fails for empty strings as of libgd 2.3.0 (#633) We change the return type of `textLayout()` to `ssize_t`, and signal failure by returning `-1`, so that laying out an empty string is no longer handled as failure. We make sure that no overflow occurs, assuming that all `int` values can be fully represented as `ssize_t`. --- src/gdft.c | 18 +++++++++--------- tests/gdimagestringft/.gitignore | 1 + tests/gdimagestringft/CMakeLists.txt | 1 + tests/gdimagestringft/Makemodule.am | 1 + tests/gdimagestringft/bug00615.c | 25 +++++++++++++++++++++++++ 5 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 tests/gdimagestringft/bug00615.c diff --git a/src/gdft.c b/src/gdft.c index b483b383..186eefff 100644 --- a/src/gdft.c +++ b/src/gdft.c @@ -441,7 +441,7 @@ typedef struct { uint32_t cluster; } glyphInfo; -static size_t +static ssize_t textLayout(uint32_t *text, int len, FT_Face face, gdFTStringExtraPtr strex, glyphInfo **glyph_info) @@ -459,19 +459,19 @@ textLayout(uint32_t *text, int len, !raqm_set_par_direction (rq, RAQM_DIRECTION_DEFAULT) || !raqm_layout (rq)) { raqm_destroy (rq); - return 0; + return -1; } glyphs = raqm_get_glyphs (rq, &count); if (!glyphs) { raqm_destroy (rq); - return 0; + return -1; } info = (glyphInfo*) gdMalloc (sizeof (glyphInfo) * count); if (!info) { raqm_destroy (rq); - return 0; + return -1; } for (i = 0; i < count; i++) { @@ -489,7 +489,7 @@ textLayout(uint32_t *text, int len, FT_Error err; info = (glyphInfo*) gdMalloc (sizeof (glyphInfo) * len); if (!info) { - return 0; + return -1; } for (count = 0; count < len; count++) { /* Convert character code to glyph index */ @@ -508,7 +508,7 @@ textLayout(uint32_t *text, int len, err = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT); if (err) { gdFree (info); - return 0; + return -1; } info[count].index = glyph_index; info[count].x_offset = 0; @@ -527,7 +527,7 @@ textLayout(uint32_t *text, int len, #endif *glyph_info = info; - return count; + return count <= SSIZE_MAX ? count : -1; } /********************************************************************/ @@ -1108,7 +1108,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, const c char *tmpstr = 0; uint32_t *text; glyphInfo *info = NULL; - size_t count; + ssize_t count; int render = (im && (im->trueColor || (fg <= 255 && fg >= -255))); FT_BitmapGlyph bm; /* 2.0.13: Bob Ostermann: don't force autohint, that's just for testing @@ -1409,7 +1409,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, const c count = textLayout (text , i, face, strex, &info); - if (!count) { + if (count < 0) { gdFree (text); gdFree (tmpstr); gdCacheDelete (tc_cache); diff --git a/tests/gdimagestringft/CMakeLists.txt b/tests/gdimagestringft/CMakeLists.txt index f46b9006..42868a27 100644 --- a/tests/gdimagestringft/CMakeLists.txt +++ b/tests/gdimagestringft/CMakeLists.txt @@ -1,5 +1,6 @@ IF(FREETYPE_FOUND) LIST(APPEND TESTS_FILES + bug00615 gdimagestringft_bbox ) ENDIF(FREETYPE_FOUND) diff --git a/tests/gdimagestringft/Makemodule.am b/tests/gdimagestringft/Makemodule.am index 0dfe26fb..a62081f4 100644 --- a/tests/gdimagestringft/Makemodule.am +++ b/tests/gdimagestringft/Makemodule.am @@ -1,5 +1,6 @@ if HAVE_LIBFREETYPE libgd_test_programs += \ + gdimagestringft/bug00615 \ gdimagestringft/gdimagestringft_bbox endif diff --git a/tests/gdimagestringft/bug00615.c b/tests/gdimagestringft/bug00615.c new file mode 100644 index 00000000..0da51dae --- /dev/null +++ b/tests/gdimagestringft/bug00615.c @@ -0,0 +1,25 @@ +/** + * Test that rendering an empty string does not fail + * + * Rendering an empty string with gdImageStringFT() is not supposed to fail; + * it is just a no-op. + * + * See + */ + +#include "gd.h" +#include "gdtest.h" + +int main() +{ + gdImagePtr im = gdImageCreate(100, 100); + + int rect[8]; + int fg = gdImageColorAllocate(im, 255, 255, 255); + char *path = gdTestFilePath("freetype/DejaVuSans.ttf"); + char *res = gdImageStringFT(im, rect, fg, path, 12, 0, 10, 10, ""); + + gdTestAssert(res == NULL); + + return gdNumFailures(); +} From 0be6aec0fe11dce8b8a5674eea5ee23bc700042e Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 15 Jul 2020 08:56:08 +0200 Subject: [PATCH] Fix #615 using libraqm and avoid unneeded free --- src/gdft.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gdft.c b/src/gdft.c index 186eefff..7eb97077 100644 --- a/src/gdft.c +++ b/src/gdft.c @@ -449,6 +449,10 @@ textLayout(uint32_t *text, int len, size_t count; glyphInfo *info; + if (!len) { + return 0; + } + #ifdef HAVE_LIBRAQM size_t i; raqm_glyph_t *glyphs; @@ -1566,7 +1570,9 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, const c } gdFree(text); - gdFree(info); + if (info) { + gdFree(info); + } /* Save the (unkerned) advance from the last character in the xshow vector */ if (strex && (strex->flags & gdFTEX_XSHOW) && strex->xshow) {