From 3cb60c39737208ca073842f4f0386d5e5c278705 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Mar 2010 19:20:32 +0100 Subject: awk: fix the case where nested "for" loops with the same variable misbehave Signed-off-by: Denys Vlasenko --- editors/awk.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'editors') diff --git a/editors/awk.c b/editors/awk.c index b9bc01f16..5cc4adce7 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -912,8 +912,10 @@ static void nvfree(var *v) free(p->x.array->items); free(p->x.array); } - if (p->type & VF_WALK) + if (p->type & VF_WALK) { + //bb_error_msg("free(walker@%p:%p) #1", &p->x.walker, p->x.walker); free(p->x.walker); + } clrvar(p); } @@ -1724,18 +1726,20 @@ static void hashwalk_init(var *v, xhash *array) char **w; hash_item *hi; unsigned i; - - if (v->type & VF_WALK) - free(v->x.walker); + char **prev_walker = (v->type & VF_WALK) ? v->x.walker : NULL; v->type |= VF_WALK; - w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen); - w[0] = w[1] = (char *)(w + 2); + + /* walker structure is: "[ptr2end][ptr2start][prev]NULNUL" */ + w = v->x.walker = xzalloc(2 + 3*sizeof(char *) + array->glen); + //bb_error_msg("walker@%p=%p", &v->x.walker, v->x.walker); + w[0] = w[1] = (char *)(w + 3); + w[2] = (char *)prev_walker; for (i = 0; i < array->csize; i++) { hi = array->items[i]; while (hi) { - strcpy(*w, hi->name); - nextword(w); + strcpy(w[0], hi->name); + nextword(&w[0]); hi = hi->next; } } @@ -1746,10 +1750,16 @@ static int hashwalk_next(var *v) char **w; w = v->x.walker; - if (w[1] == w[0]) + if (w[1] == w[0]) { + char **prev_walker = (char**)w[2]; + + //bb_error_msg("free(walker@%p:%p) #3, restoring to %p", &v->x.walker, v->x.walker, prev_walker); + free(v->x.walker); + v->x.walker = prev_walker; return FALSE; + } - setvar_s(v, nextword(w+1)); + setvar_s(v, nextword(&w[1])); return TRUE; } -- cgit v1.2.3