diff options
author | Denys Vlasenko | 2010-03-11 12:13:18 +0100 |
---|---|---|
committer | Denys Vlasenko | 2010-03-11 12:13:18 +0100 |
commit | da62b09ab1def06ed8844c4df7b7eacf05474284 (patch) | |
tree | 5555dcabc789f27d026adc0fac2c39274e938b3c | |
parent | 90f19fa468d5b9f6374a62343e98066be8169140 (diff) | |
download | busybox-da62b09ab1def06ed8844c4df7b7eacf05474284.zip busybox-da62b09ab1def06ed8844c4df7b7eacf05474284.tar.gz |
awk: be more paranoid when freeing loop variable; make code less obfuscated
function old new delta
nvfree 149 170 +21
next_token 928 932 +4
getvar_i 95 94 -1
skip_spaces 51 45 -6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/2 up/down: 25/-7) Total: 18 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/editors/awk.c b/editors/awk.c index 1d704e8..397d70f 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -14,6 +14,16 @@ /* This is a NOEXEC applet. Be very careful! */ +/* If you comment out one of these below, it will be #defined later + * to perform debug printfs to stderr: */ +#define debug_printf_walker(...) do {} while (0) + +#ifndef debug_printf_walker +# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) +#endif + + + #define MAXVARFMT 240 #define MINNVBLOCK 64 @@ -32,6 +42,13 @@ /* these flags are static, don't change them when value is changed */ #define VF_DONTTOUCH (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY) +typedef struct walker_list { + char *end; + char *cur; + struct walker_list *prev; + char wbuf[1]; +} walker_list; + /* Variable */ typedef struct var_s { unsigned type; /* flags */ @@ -41,7 +58,7 @@ typedef struct var_s { int aidx; /* func arg idx (for compilation stage) */ struct xhash_s *array; /* array ptr */ struct var_s *parent; /* for func args, ptr to actual parameter */ - char **walker; /* list of array elements (for..in) */ + walker_list *walker; /* list of array elements (for..in) */ } x; } var; @@ -913,10 +930,17 @@ static void nvfree(var *v) free(p->x.array); } if (p->type & VF_WALK) { - //bb_error_msg("free(walker@%p:%p) #1", &p->x.walker, p->x.walker); - free(p->x.walker); + walker_list *n; + walker_list *w = p->x.walker; + debug_printf_walker("nvfree: freeing walker @%p\n", &p->x.walker); + p->x.walker = NULL; + while (w) { + n = w->prev; + debug_printf_walker(" free(%p)\n", w); + free(w); + w = n; + } } - clrvar(p); } @@ -1724,23 +1748,28 @@ static node *nextarg(node **pn) static void hashwalk_init(var *v, xhash *array) { - char **w; hash_item *hi; unsigned i; - char **prev_walker = (v->type & VF_WALK) ? v->x.walker : NULL; + walker_list *w; + walker_list *prev_walker; - v->type |= VF_WALK; + if (v->type & VF_WALK) { + prev_walker = v->x.walker; + } else { + v->type |= VF_WALK; + prev_walker = NULL; + } + debug_printf_walker("hashwalk_init: prev_walker:%p\n", prev_walker); - /* 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; + w = v->x.walker = xzalloc(sizeof(*w) + array->glen + 1); /* why + 1? */ + debug_printf_walker(" walker@%p=%p\n", &v->x.walker, w); + w->cur = w->end = w->wbuf; + w->prev = prev_walker; for (i = 0; i < array->csize; i++) { hi = array->items[i]; while (hi) { - strcpy(w[0], hi->name); - nextword(&w[0]); + strcpy(w->end, hi->name); + nextword(&w->end); hi = hi->next; } } @@ -1748,19 +1777,18 @@ static void hashwalk_init(var *v, xhash *array) static int hashwalk_next(var *v) { - char **w; + walker_list *w = v->x.walker; - w = v->x.walker; - if (w[1] == w[0]) { - char **prev_walker = (char**)w[2]; + if (w->cur >= w->end) { + walker_list *prev_walker = w->prev; - //bb_error_msg("free(walker@%p:%p) #3, restoring to %p", &v->x.walker, v->x.walker, prev_walker); - free(v->x.walker); + debug_printf_walker("end of iteration, free(walker@%p:%p), prev_walker:%p\n", &v->x.walker, w, prev_walker); + free(w); v->x.walker = prev_walker; return FALSE; } - setvar_s(v, nextword(&w[1])); + setvar_s(v, nextword(&w->cur)); return TRUE; } |