From eb880d3cac68992d99b68aa3da675ad57dc0b069 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Sun, 3 Mar 2019 12:29:21 +0100
Subject: [PATCH] Image.GIF: Use a string_builder instead of the stack.

Avoid running out of stack in _decode() et al, by using
a string_builder to concatenate string fragments.
---
 .gitattributes                     |  1 -
 src/modules/_Image_GIF/image_gif.c | 75 ++++++++++++++++++------------
 2 files changed, 45 insertions(+), 31 deletions(-)

diff --git a/.gitattributes b/.gitattributes
index 2b488fc65e..79b8b1b4f4 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -659,7 +659,6 @@ testfont binary
 /src/modules/_Image_GIF/configure.in foreign_ident
 /src/modules/_Image_GIF/gif_lzw.c foreign_ident
 /src/modules/_Image_GIF/gif_lzw.h foreign_ident
-/src/modules/_Image_GIF/image_gif.c foreign_ident
 /src/modules/_Image_JPEG/Makefile.in foreign_ident
 /src/modules/_Image_JPEG/acconfig.h foreign_ident
 /src/modules/_Image_JPEG/configure.in foreign_ident
diff --git a/src/modules/_Image_GIF/image_gif.c b/src/modules/_Image_GIF/image_gif.c
index a68071a36c..fd1f604ba1 100644
--- a/src/modules/_Image_GIF/image_gif.c
+++ b/src/modules/_Image_GIF/image_gif.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: image_gif.c,v 1.22 2005/05/06 00:46:32 nilsson Exp $
+|| $Id$
 */
 
 /*
@@ -1301,11 +1301,9 @@ static void _decode_get_extension(unsigned char **s,
 				  size_t *len)
 {
    int ext;
-   size_t n,sz;
 
    if (*len<3) { (*s)+=*len; (*len)=0; return; }
-   n=0;
-   
+
    ext=(*s)[1];
    
    (*len)-=2;
@@ -1315,22 +1313,31 @@ static void _decode_get_extension(unsigned char **s,
 
    push_int(ext);
 
-   while (*len && (sz=**s))
-   {
-      if ((*len)-1<sz) sz=(*len)-1;
+   if (*len && **s) {
+      struct string_builder data;
+      ONERROR uwp;
+      size_t sz;
 
-      push_string(make_shared_binary_string((char *)(*s)+1,sz));
-      n++;
+      init_string_builder_alloc(&data, **s, 0);
+      SET_ONERROR(uwp, free_string_builder, &data);
 
-      (*len)-=(sz+1);
-      (*s)+=(sz+1);
-   }
-   if (*len) { (*len)-=1; (*s)+=1; }
+      while (*len && (sz=**s))
+      {
+	 if ((*len)-1<sz) sz=(*len)-1;
 
-   if (!n)
+	 string_builder_binary_strcat0(&data, (*s)+1, sz);
+
+	 (*len)-=(sz+1);
+	 (*s)+=(sz+1);
+      }
+
+      push_string(finish_string_builder(&data));
+      UNSET_ONERROR(uwp);
+   } else {
       push_empty_string();
-   else
-      f_add(DO_NOT_WARN(n));
+   }
+
+   if (*len) { (*len)-=1; (*s)+=1; }
 
    f_aggregate(3);
 }
@@ -1338,8 +1345,7 @@ static void _decode_get_extension(unsigned char **s,
 static void _decode_get_render(unsigned char **s,
 			       size_t *len)
 {
-   int n=0,bpp;
-   size_t sz;
+   int bpp;
 
 /* byte ...
    0  0x2c (render block init)
@@ -1401,22 +1407,31 @@ static void _decode_get_render(unsigned char **s,
 
    if (*len) { push_int(**s); (*s)++; (*len)--; } else push_int(0);
 
-   while (*len && (sz=**s))
-   {
-      if ((*len)-1<sz) sz=(*len)-1;
+   if (*len && **s) {
+      struct string_builder data;
+      ONERROR uwp;
+      size_t sz;
 
-      push_string(make_shared_binary_string((char *)(*s)+1,sz));
-      n++;
+      init_string_builder_alloc(&data, **s, 0);
+      SET_ONERROR(uwp, free_string_builder, &data);
 
-      (*len)-=(sz+1);
-      (*s)+=(sz+1);
-   }
-   if (*len) { (*len)-=1; (*s)+=1; }
+      while (*len && (sz=**s))
+      {
+	 if ((*len)-1<sz) sz=(*len)-1;
+
+	 string_builder_binary_strcat0(&data, (*s)+1, sz);
 
-   if (!n)
+	 (*len)-=(sz+1);
+	 (*s)+=(sz+1);
+      }
+
+      push_string(finish_string_builder(&data));
+      UNSET_ONERROR(uwp);
+   } else {
       push_empty_string();
-   else
-      f_add(n);
+   }
+
+   if (*len) { (*len)-=1; (*s)+=1; }
 
    f_aggregate(9);
 }
-- 
GitLab