awk: fix the case where nested "for" loops with the same variable misbehave

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-03-10 19:20:32 +01:00
parent eae697fb93
commit 3cb60c3973
2 changed files with 59 additions and 11 deletions

View File

@ -912,8 +912,10 @@ static void nvfree(var *v)
free(p->x.array->items); free(p->x.array->items);
free(p->x.array); 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); free(p->x.walker);
}
clrvar(p); clrvar(p);
} }
@ -1724,18 +1726,20 @@ static void hashwalk_init(var *v, xhash *array)
char **w; char **w;
hash_item *hi; hash_item *hi;
unsigned i; unsigned i;
char **prev_walker = (v->type & VF_WALK) ? v->x.walker : NULL;
if (v->type & VF_WALK)
free(v->x.walker);
v->type |= VF_WALK; 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]<word1>NUL<word2>NUL" */
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++) { for (i = 0; i < array->csize; i++) {
hi = array->items[i]; hi = array->items[i];
while (hi) { while (hi) {
strcpy(*w, hi->name); strcpy(w[0], hi->name);
nextword(w); nextword(&w[0]);
hi = hi->next; hi = hi->next;
} }
} }
@ -1746,10 +1750,16 @@ static int hashwalk_next(var *v)
char **w; char **w;
w = v->x.walker; w = v->x.walker;
if (w[1] == w[0]) if (w[1] == w[0]) {
return FALSE; char **prev_walker = (char**)w[2];
setvar_s(v, nextword(w+1)); //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]));
return TRUE; return TRUE;
} }

View File

@ -67,4 +67,42 @@ testing "awk string cast (bug 725)" \
testing "awk handles whitespace before array subscript" \ testing "awk handles whitespace before array subscript" \
"awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" "" "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" ""
prg='
BEGIN {
v["q"]=1
v["w"]=1
v["e"]=1
for (l in v) {
print "outer1", l;
for (l in v) {
print " inner", l;
}
print "outer2", l;
}
print "end", l;
l="a"
exit;
}'
testing "awk nested loops with the same variable" \
"awk '$prg'" \
"\
outer1 e
inner e
inner q
inner w
outer2 w
outer1 q
inner e
inner q
inner w
outer2 w
outer1 w
inner e
inner q
inner w
outer2 w
end w
" \
"" ""
exit $FAILCOUNT exit $FAILCOUNT