From 2ce07ac9deb8304e56248f1882eb76089aaa72ec Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Thu, 6 May 2021 00:05:58 -0700 Subject: [PATCH] Fill: Avoid infinite recursion crash simulate_flood_fill_outside_check() could spin in an infinite loop because it could sometimes set values in the `touched[]` array to 0, which means the spot was never seen. Values going in there are not boolean, but a 0-255 gradient, for smoother fills on antialiased edges. This change forces it to be a 1-255 value, ensuring that a 'touched' spot on the canvas will have a non-zero `touched[]` value. h/t Pere for noticing the bug, providing some details, and best of all providing a sample image to play with which consistently invoked the crash. (It made mending this a 10 minute task for me, rather than an hours-long hunt to reproduce! Big 'thanks' for doing that ahead of time!!!) --- src/fill.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/fill.c b/src/fill.c index f74648a0a..bf931c5b9 100644 --- a/src/fill.c +++ b/src/fill.c @@ -4,7 +4,7 @@ Fill tool Tux Paint - A simple drawing program for children. - Copyright (c) 2002-2019 by Bill Kendrick and others; see AUTHORS.txt + Copyright (c) 2002-2021 by Bill Kendrick and others; see AUTHORS.txt bill@newbreedsoftware.com http://www.tuxpaint.org/ @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (See COPYING.txt) - Last updated: March 8, 2021 + Last updated: May 5, 2021 $Id$ */ @@ -137,6 +137,7 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Surface * last, double in_line, closeness; static unsigned char prog_anim; Uint32 px_colr; + Uint8 touch_byt; /* "Same" color? No need to fill */ @@ -187,7 +188,11 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Surface * last, } if (touched != NULL) { - touched[(y * canvas->w) + fillL] = (255 - ((Uint8) (in_line * 85))); + touch_byt = (255 - ((Uint8) (in_line * 85))); + if (touch_byt == 0) + touch_byt = 1; + + touched[(y * canvas->w) + fillL] = touch_byt; } px_colr = getpixels[last->format->BytesPerPixel] (last, fillL, y); @@ -210,7 +215,11 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Surface * last, { if (touched != NULL) { - touched[(y * canvas->w) + fillL] = (255 - ((Uint8) (in_line * 85))); + touch_byt = (255 - ((Uint8) (in_line * 85))); + if (touch_byt == 0) + touch_byt = 1; + + touched[(y * canvas->w) + fillL] = touch_byt; } px_colr = getpixels[last->format->BytesPerPixel] (last, fillL, y); @@ -240,7 +249,11 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Surface * last, } if (touched != NULL) { - touched[(y * canvas->w) + fillR] = (255 - ((Uint8) (in_line * 85))); + touch_byt = (255 - ((Uint8) (in_line * 85))); + if (touch_byt == 0) + touch_byt = 1; + + touched[(y * canvas->w) + fillR] = touch_byt; } px_colr = getpixels[last->format->BytesPerPixel] (last, fillR, y); @@ -263,7 +276,11 @@ void simulate_flood_fill_outside_check(SDL_Surface * screen, SDL_Surface * last, { if (touched != NULL) { - touched[(y * canvas->w) + fillR] = (255 - ((Uint8) (in_line * 85))); + touch_byt = (255 - ((Uint8) (in_line * 85))); + if (touch_byt == 0) + touch_byt = 1; + + touched[(y * canvas->w) + fillR] = touch_byt; } px_colr = getpixels[last->format->BytesPerPixel] (last, fillR, y);