From 9e7605286d6cddc03a807ca0a515d7af2f7b0bc5 Mon Sep 17 00:00:00 2001
From: Arne Goedeke <el@laramies.com>
Date: Thu, 11 Apr 2013 12:55:22 +0200
Subject: [PATCH] array implode: fixed buffer overrun

When using array implode with zero elements it was possible to write the delimiter
into the newly created string too many times, resulting in a buffer overrun.
This bug has been introduced by commit 2f27ebab1.
---
 src/array.c | 45 +++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/src/array.c b/src/array.c
index 1a69c8b554..562c73e6ef 100644
--- a/src/array.c
+++ b/src/array.c
@@ -2409,13 +2409,14 @@ PMOD_EXPORT struct array *explode(struct pike_string *str,
 PMOD_EXPORT struct pike_string *implode(struct array *a,
                                         struct pike_string *del)
 {
-  INT32 len, e;
+  INT32 len, e, delims;
   PCHARP r;
   struct pike_string *ret;
   struct svalue *ae;
   int max_shift = del->size_shift;
 
   len=0;
+  delims = 0;
 
   for(e=a->size, ae=a->item; e--; ae++)
     switch(TYPEOF(*ae))
@@ -2427,43 +2428,39 @@ PMOD_EXPORT struct pike_string *implode(struct array *a,
       default:
 	Pike_error("Array element %d is not a string\n", ae-a->item);
       case T_STRING:
+	delims++;
         len+=ae->u.string->len + del->len;
         if(ae->u.string->size_shift > max_shift)
 	  max_shift=ae->u.string->size_shift;
 	break;
     }
-  if(len) len-=del->len;
+
+  if(delims)
+  {
+    len-=del->len;
+    delims--;
+  }
   
   ret=begin_wide_shared_string(len,max_shift);
   r=MKPCHARP_STR(ret);
   len = del->len;
   if((e = a->size))
-    for(ae=a->item;;ae++)
+    for(ae=a->item;e--;ae++)
     {
-      switch(TYPEOF(*ae))
-      {
-        case T_STRING:
-        {
-          struct pike_string *tmp = ae->u.string;
-          pike_string_cpy(r,tmp);
-          INC_PCHARP(r,tmp->len);
-          break;
-        }
-        default:
-        case T_INT:
-          if(!--e)
-	    goto ret;
-          continue;
-      }
-      if(!--e)
-        break;
-      if(len)
+      if (TYPEOF(*ae) == T_STRING)
       {
-        pike_string_cpy(r,del);
-        INC_PCHARP(r,len);
+	struct pike_string *tmp = ae->u.string;
+	pike_string_cpy(r,tmp);
+	INC_PCHARP(r,tmp->len);
+	if(len && delims)
+	{
+	  delims--;
+	  pike_string_cpy(r,del);
+	  INC_PCHARP(r,len);
+	}
       }
     }
-ret:
+
   return low_end_shared_string(ret);
 }
 
-- 
GitLab