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