SDL_image: GIF: reduce stack usage by dynamically allocating state. (5d792)

From 5d792dde2f764daf15dc48521774a3354330db69 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Sun, 14 Mar 2021 17:00:02 +0300
Subject: [PATCH] GIF: reduce stack usage by dynamically allocating state.

---
 IMG_gif.c | 50 +++++++++++++++++++++++++++-----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/IMG_gif.c b/IMG_gif.c
index d5d963e..48a8055 100644
--- a/IMG_gif.c
+++ b/IMG_gif.c
@@ -177,11 +177,8 @@ IMG_LoadGIF_RW(SDL_RWops *src)
     int imageCount = 0;
     char version[4];
     int imageNumber = 1;
+    State_t *state = NULL;
     Image *image = NULL;
-    State_t state;
-    state.ZeroDataBlock = FALSE;
-    state.fresh = FALSE;
-    state.last_byte = 0;
 
     if ( src == NULL ) {
 	return NULL;
@@ -203,25 +200,30 @@ IMG_LoadGIF_RW(SDL_RWops *src)
 	RWSetMsg("bad version number, not '87a' or '89a'");
         goto done;
     }
-    state.Gif89.transparent = -1;
-    state.Gif89.delayTime = -1;
-    state.Gif89.inputFlag = -1;
-    state.Gif89.disposal = 0;
+    state = (State_t *)calloc(1, sizeof(State_t));
+    if (state == NULL) {
+	RWSetMsg("Out of memory");
+	goto done;
+    }
+    state->Gif89.transparent = -1;
+    state->Gif89.delayTime = -1;
+    state->Gif89.inputFlag = -1;
+    state->Gif89.disposal = 0;
 
     if (!ReadOK(src, buf, 7)) {
 	RWSetMsg("failed to read screen descriptor");
         goto done;
     }
-    state.GifScreen.Width = LM_to_uint(buf[0], buf[1]);
-    state.GifScreen.Height = LM_to_uint(buf[2], buf[3]);
-    state.GifScreen.BitPixel = 2 << (buf[4] & 0x07);
-    state.GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
-    state.GifScreen.Background = buf[5];
-    state.GifScreen.AspectRatio = buf[6];
+    state->GifScreen.Width = LM_to_uint(buf[0], buf[1]);
+    state->GifScreen.Height = LM_to_uint(buf[2], buf[3]);
+    state->GifScreen.BitPixel = 2 << (buf[4] & 0x07);
+    state->GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
+    state->GifScreen.Background = buf[5];
+    state->GifScreen.AspectRatio = buf[6];
 
     if (BitSet(buf[4], LOCALCOLORMAP)) {	/* Global Colormap */
-	if (ReadColorMap(src, state.GifScreen.BitPixel,
-			 state.GifScreen.ColorMap, &state.GifScreen.GrayScale)) {
+	if (ReadColorMap(src, state->GifScreen.BitPixel,
+			 state->GifScreen.ColorMap, &state->GifScreen.GrayScale)) {
 	    RWSetMsg("error reading global colormap");
             goto done;
 	}
@@ -243,7 +245,7 @@ IMG_LoadGIF_RW(SDL_RWops *src)
 		RWSetMsg("EOF / read error on extention function code");
                 goto done;
 	    }
-	    DoExtension(src, c, &state);
+	    DoExtension(src, c, state);
 	    continue;
 	}
 	if (c != ',') {		/* Not a valid start character */
@@ -268,19 +270,19 @@ IMG_LoadGIF_RW(SDL_RWops *src)
 			      LM_to_uint(buf[6], buf[7]),
 			      bitPixel, localColorMap, grayScale,
 			      BitSet(buf[8], INTERLACE),
-			      imageCount != imageNumber, &state);
+			      imageCount != imageNumber, state);
 	} else {
 	    image = ReadImage(src, LM_to_uint(buf[4], buf[5]),
 			      LM_to_uint(buf[6], buf[7]),
-			      state.GifScreen.BitPixel, state.GifScreen.ColorMap,
-			      state.GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
-			      imageCount != imageNumber, &state);
+			      state->GifScreen.BitPixel, state->GifScreen.ColorMap,
+			      state->GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
+			      imageCount != imageNumber, state);
 	}
     } while (image == NULL);
 
 #ifdef USED_BY_SDL
-    if ( state.Gif89.transparent >= 0 ) {
-        SDL_SetColorKey(image, SDL_SRCCOLORKEY, state.Gif89.transparent);
+    if ( state->Gif89.transparent >= 0 ) {
+        SDL_SetColorKey(image, SDL_SRCCOLORKEY, state->Gif89.transparent);
     }
 #endif
 
@@ -288,6 +290,8 @@ IMG_LoadGIF_RW(SDL_RWops *src)
     if ( image == NULL ) {
         SDL_RWseek(src, start, RW_SEEK_SET);
     }
+
+    free(state);
     return image;
 }