From 78cd777a68a968f58de273b8744ffffbcc5c2024 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 4 Jan 2025 14:22:52 +0100 Subject: [PATCH 1/2] Port "improve _gdImageFillTiled() internal function" This improvement was done for libgd 2.1.0[1], and the erroneous calculation has been fixed as of libgd 2.2.0[2]. While we're at it we also add the overflow checks of external libgd; these are not really necessary, since `.sx * .sy` overflow was already prevented when the image has been created, and since we're using `safe_emalloc()` the `struct seg` overflow is also prevented. It should be noted that `overflow2()` prevents `int` overflow, while `safe_emalloc()` prevents `size_t` overflow, so the former is more restrictive. For parity with external libgd, this still appears to be a good thing. [1] [2] --- ext/gd/libgd/gd.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index 2a1b5563b3d31..380187b0eb22e 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -2026,6 +2026,14 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc) goto done; } + if(overflow2(im->sy, im->sx)) { + return; + } + + if(overflow2(sizeof(struct seg), ((im->sy * im->sx) / 4))) { + return; + } + stack = (struct seg *)safe_emalloc(sizeof(struct seg), ((int)(im->sy*im->sx)/4), 1); sp = stack; @@ -2079,7 +2087,7 @@ static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) /* stack of filled segments */ struct seg *stack; struct seg *sp; - char **pts; + char *pts; if (!im->tile) { return; @@ -2089,11 +2097,16 @@ static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) nc = gdImageTileGet(im,x,y); - pts = (char **) ecalloc(im->sy + 1, sizeof(char *)); - for (i = 0; i < im->sy + 1; i++) { - pts[i] = (char *) ecalloc(im->sx + 1, sizeof(char)); + if(overflow2(im->sy, im->sx)) { + return; } + if(overflow2(sizeof(struct seg), ((im->sy * im->sx) / 4))) { + return; + } + + pts = (char *) ecalloc(im->sy * im->sx, sizeof(char)); + stack = (struct seg *)safe_emalloc(sizeof(struct seg), ((int)(im->sy*im->sx)/4), 1); sp = stack; @@ -2105,9 +2118,9 @@ static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) FILL_PUSH(y+1, x, x, -1); while (sp>stack) { FILL_POP(y, x1, x2, dy); - for (x=x1; x>=0 && (!pts[y][x] && gdImageGetPixel(im,x,y)==oc); x--) { + for (x=x1; x>=0 && (!pts[y + x*wy2] && gdImageGetPixel(im,x,y)==oc); x--) { nc = gdImageTileGet(im,x,y); - pts[y][x] = 1; + pts[y + x*wy2] = 1; gdImageSetPixel(im,x, y, nc); } if (x>=x1) { @@ -2121,9 +2134,9 @@ static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) } x = x1+1; do { - for(; xsy + 1; i++) { - efree(pts[i]); - } - efree(pts); efree(stack); } From a5a3beffee89d47e50289b4ba0f238f831b7625d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 4 Jan 2025 16:27:50 +0100 Subject: [PATCH 2/2] Remove unused variable --- ext/gd/libgd/gd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index 380187b0eb22e..a87e7131375d9 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -2081,7 +2081,7 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc) static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) { - int i, l, x1, x2, dy; + int l, x1, x2, dy; int oc; /* old pixel value */ int wx2,wy2; /* stack of filled segments */