From e52c2c88eeb8f95f2910d43c1fc42a7db2f378d0 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Sun, 14 Mar 2021 17:00:32 +0300
Subject: [PATCH] GIF: reduce stack usage by dynamically allocating state.
---
IMG_gif.c | 58 ++++++++++++++++++++++++++++---------------------------
1 file changed, 30 insertions(+), 28 deletions(-)
diff --git a/IMG_gif.c b/IMG_gif.c
index a3ff70d..8e20f41 100644
--- a/IMG_gif.c
+++ b/IMG_gif.c
@@ -209,14 +209,10 @@ IMG_LoadGIF_RW_Internal(SDL_RWops *src, SDL_bool load_anim)
int useGlobalColormap;
int bitPixel;
char version[4];
+ State_t *state = NULL;
Image *image = NULL;
Anim_t *anim;
Frame_t *frames, *frame;
- State_t state;
-
- state.ZeroDataBlock = FALSE;
- state.fresh = FALSE;
- state.last_byte = 0;
if (src == NULL) {
return NULL;
@@ -243,25 +239,30 @@ IMG_LoadGIF_RW_Internal(SDL_RWops *src, SDL_bool load_anim)
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 = GIF_DISPOSE_NA;
+ state = (State_t *)SDL_calloc(1, sizeof(State_t));
+ if (state == NULL) {
+ SDL_OutOfMemory();
+ goto done;
+ }
+ state->Gif89.transparent = -1;
+ state->Gif89.delayTime = -1;
+ state->Gif89.inputFlag = -1;
+ state->Gif89.disposal = GIF_DISPOSE_NA;
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;
}
@@ -279,7 +280,7 @@ IMG_LoadGIF_RW_Internal(SDL_RWops *src, SDL_bool load_anim)
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 */
@@ -303,18 +304,18 @@ IMG_LoadGIF_RW_Internal(SDL_RWops *src, SDL_bool load_anim)
LM_to_uint(buf[6], buf[7]),
bitPixel, localColorMap, grayScale,
BitSet(buf[8], INTERLACE),
- 0, &state);
+ 0, 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),
- 0, &state);
+ state->GifScreen.BitPixel, state->GifScreen.ColorMap,
+ state->GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
+ 0, state);
}
if (image) {
- if (state.Gif89.transparent >= 0) {
- SDL_SetColorKey(image, SDL_TRUE, state.Gif89.transparent);
+ if (state->Gif89.transparent >= 0) {
+ SDL_SetColorKey(image, SDL_TRUE, state->Gif89.transparent);
}
frames = (Frame_t *)SDL_realloc(anim->frames, (anim->count + 1) * sizeof(*anim->frames));
@@ -329,11 +330,11 @@ IMG_LoadGIF_RW_Internal(SDL_RWops *src, SDL_bool load_anim)
frame->image = image;
frame->x = LM_to_uint(buf[0], buf[1]);
frame->y = LM_to_uint(buf[2], buf[3]);
- frame->disposal = state.Gif89.disposal;
- if (state.Gif89.delayTime < 2) {
+ frame->disposal = state->Gif89.disposal;
+ if (state->Gif89.delayTime < 2) {
frame->delay = 100; /* Default animation delay, matching browsers and Qt */
} else {
- frame->delay = state.Gif89.delayTime * 10;
+ frame->delay = state->Gif89.delayTime * 10;
}
if (!load_anim) {
@@ -357,8 +358,9 @@ IMG_LoadGIF_RW_Internal(SDL_RWops *src, SDL_bool load_anim)
if (anim->count == 0) {
SDL_free(anim->frames);
SDL_free(anim);
- return NULL;
+ anim = NULL;
}
+ SDL_free(state);
return anim;
}