diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-23 12:50:54 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-23 12:50:54 +0000 |
| commit | f962a0354e2426ef9781df97e4b02b32e438783c (patch) | |
| tree | 4e0b3363932fbc0a30d5242b58ca5a0fea48d2a8 /shell | |
| parent | f23c3f95e88302923147f159115180da7cf0344e (diff) | |
| download | busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.tar.gz busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.tar.bz2 busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.zip | |
hush: plug memory leak
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 43 | ||||
| -rw-r--r-- | shell/hush_leaktool.sh | 13 | ||||
| -rwxr-xr-x | shell/hush_test/hush-z_slow/leak_var.tests | 56 | ||||
| -rwxr-xr-x | shell/hush_test/run-all | 1 |
4 files changed, 91 insertions, 22 deletions
diff --git a/shell/hush.c b/shell/hush.c index a76327721..5c641904c 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -144,6 +144,40 @@ static const char *indenter(int i) | |||
| 144 | #endif | 144 | #endif |
| 145 | 145 | ||
| 146 | 146 | ||
| 147 | /* | ||
| 148 | * Leak hunting. Use hush_leaktool.sh for post-processing. | ||
| 149 | */ | ||
| 150 | #ifdef FOR_HUSH_LEAKTOOL | ||
| 151 | void *xxmalloc(int lineno, size_t size) | ||
| 152 | { | ||
| 153 | void *ptr = xmalloc((size + 0xff) & ~0xff); | ||
| 154 | fprintf(stderr, "line %d: malloc %p\n", lineno, ptr); | ||
| 155 | return ptr; | ||
| 156 | } | ||
| 157 | void *xxrealloc(int lineno, void *ptr, size_t size) | ||
| 158 | { | ||
| 159 | ptr = xrealloc(ptr, (size + 0xff) & ~0xff); | ||
| 160 | fprintf(stderr, "line %d: realloc %p\n", lineno, ptr); | ||
| 161 | return ptr; | ||
| 162 | } | ||
| 163 | char *xxstrdup(int lineno, const char *str) | ||
| 164 | { | ||
| 165 | char *ptr = xstrdup(str); | ||
| 166 | fprintf(stderr, "line %d: strdup %p\n", lineno, ptr); | ||
| 167 | return ptr; | ||
| 168 | } | ||
| 169 | void xxfree(void *ptr) | ||
| 170 | { | ||
| 171 | fprintf(stderr, "free %p\n", ptr); | ||
| 172 | free(ptr); | ||
| 173 | } | ||
| 174 | #define xmalloc(s) xxmalloc(__LINE__, s) | ||
| 175 | #define xrealloc(p, s) xxrealloc(__LINE__, p, s) | ||
| 176 | #define xstrdup(s) xxstrdup(__LINE__, s) | ||
| 177 | #define free(p) xxfree(p) | ||
| 178 | #endif | ||
| 179 | |||
| 180 | |||
| 147 | #if !ENABLE_HUSH_INTERACTIVE | 181 | #if !ENABLE_HUSH_INTERACTIVE |
| 148 | #undef ENABLE_FEATURE_EDITING | 182 | #undef ENABLE_FEATURE_EDITING |
| 149 | #define ENABLE_FEATURE_EDITING 0 | 183 | #define ENABLE_FEATURE_EDITING 0 |
| @@ -256,7 +290,6 @@ struct child_prog { | |||
| 256 | smallint subshell; /* flag, non-zero if group must be forked */ | 290 | smallint subshell; /* flag, non-zero if group must be forked */ |
| 257 | smallint is_stopped; /* is the program currently running? */ | 291 | smallint is_stopped; /* is the program currently running? */ |
| 258 | struct redir_struct *redirects; /* I/O redirections */ | 292 | struct redir_struct *redirects; /* I/O redirections */ |
| 259 | char **glob_result; /* result of parameter globbing */ | ||
| 260 | struct pipe *family; /* pointer back to the child's parent pipe */ | 293 | struct pipe *family; /* pointer back to the child's parent pipe */ |
| 261 | //sp counting seems to be broken... so commented out, grep for '//sp:' | 294 | //sp counting seems to be broken... so commented out, grep for '//sp:' |
| 262 | //sp: int sp; /* number of SPECIAL_VAR_SYMBOL */ | 295 | //sp: int sp; /* number of SPECIAL_VAR_SYMBOL */ |
| @@ -2198,8 +2231,8 @@ static int free_pipe(struct pipe *pi, int indent) | |||
| 2198 | for (a = 0, p = child->argv; *p; a++, p++) { | 2231 | for (a = 0, p = child->argv; *p; a++, p++) { |
| 2199 | debug_printf_clean("%s argv[%d] = %s\n", indenter(indent), a, *p); | 2232 | debug_printf_clean("%s argv[%d] = %s\n", indenter(indent), a, *p); |
| 2200 | } | 2233 | } |
| 2201 | free_strings(child->glob_result); | 2234 | free_strings(child->argv); |
| 2202 | child->glob_result = NULL; | 2235 | child->argv = NULL; |
| 2203 | } else if (child->group) { | 2236 | } else if (child->group) { |
| 2204 | debug_printf_clean("%s begin group (subshell:%d)\n", indenter(indent), child->subshell); | 2237 | debug_printf_clean("%s begin group (subshell:%d)\n", indenter(indent), child->subshell); |
| 2205 | ret_code = free_pipe_list(child->group, indent+3); | 2238 | ret_code = free_pipe_list(child->group, indent+3); |
| @@ -2333,6 +2366,7 @@ static int xglob(o_string *dest, char ***pglob) | |||
| 2333 | debug_printf("globhack returned %d\n", gr); | 2366 | debug_printf("globhack returned %d\n", gr); |
| 2334 | /* quote removal, or more accurately, backslash removal */ | 2367 | /* quote removal, or more accurately, backslash removal */ |
| 2335 | *pglob = globhack(dest->data, *pglob); | 2368 | *pglob = globhack(dest->data, *pglob); |
| 2369 | globfree(&globdata); | ||
| 2336 | return 0; | 2370 | return 0; |
| 2337 | } | 2371 | } |
| 2338 | if (gr != 0) { /* GLOB_ABORTED ? */ | 2372 | if (gr != 0) { /* GLOB_ABORTED ? */ |
| @@ -2340,7 +2374,6 @@ static int xglob(o_string *dest, char ***pglob) | |||
| 2340 | } | 2374 | } |
| 2341 | if (globdata.gl_pathv && globdata.gl_pathv[0]) | 2375 | if (globdata.gl_pathv && globdata.gl_pathv[0]) |
| 2342 | *pglob = add_strings_to_strings(1, *pglob, globdata.gl_pathv); | 2376 | *pglob = add_strings_to_strings(1, *pglob, globdata.gl_pathv); |
| 2343 | /* globprint(glob_target); */ | ||
| 2344 | globfree(&globdata); | 2377 | globfree(&globdata); |
| 2345 | return gr; | 2378 | return gr; |
| 2346 | } | 2379 | } |
| @@ -3001,6 +3034,7 @@ static int done_word(o_string *dest, struct p_context *ctx) | |||
| 3001 | 3034 | ||
| 3002 | b_reset(dest); | 3035 | b_reset(dest); |
| 3003 | if (ctx->pending_redirect) { | 3036 | if (ctx->pending_redirect) { |
| 3037 | /* NB: don't free_strings(ctx->pending_redirect->glob_word) here */ | ||
| 3004 | if (ctx->pending_redirect->glob_word | 3038 | if (ctx->pending_redirect->glob_word |
| 3005 | && ctx->pending_redirect->glob_word[0] | 3039 | && ctx->pending_redirect->glob_word[0] |
| 3006 | && ctx->pending_redirect->glob_word[1] | 3040 | && ctx->pending_redirect->glob_word[1] |
| @@ -3056,7 +3090,6 @@ static int done_command(struct p_context *ctx) | |||
| 3056 | /*child->argv = NULL;*/ | 3090 | /*child->argv = NULL;*/ |
| 3057 | /*child->is_stopped = 0;*/ | 3091 | /*child->is_stopped = 0;*/ |
| 3058 | /*child->group = NULL;*/ | 3092 | /*child->group = NULL;*/ |
| 3059 | /*child->glob_result = NULL;*/ | ||
| 3060 | child->family = pi; | 3093 | child->family = pi; |
| 3061 | //sp: /*child->sp = 0;*/ | 3094 | //sp: /*child->sp = 0;*/ |
| 3062 | //pt: child->parse_type = ctx->parse_type; | 3095 | //pt: child->parse_type = ctx->parse_type; |
diff --git a/shell/hush_leaktool.sh b/shell/hush_leaktool.sh new file mode 100644 index 000000000..54a19aa6f --- /dev/null +++ b/shell/hush_leaktool.sh | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | # hush's stderr with leak debug enabled | ||
| 4 | output=output | ||
| 5 | |||
| 6 | freelist=`grep 'free 0x' "$output" | cut -d' ' -f2 | sort | uniq | xargs` | ||
| 7 | |||
| 8 | grep -v free "$output" >temp1 | ||
| 9 | for freed in $freelist; do | ||
| 10 | echo Dropping $freed | ||
| 11 | cat temp1 | grep -v $freed >temp2 | ||
| 12 | mv temp2 temp1 | ||
| 13 | done | ||
diff --git a/shell/hush_test/hush-z_slow/leak_var.tests b/shell/hush_test/hush-z_slow/leak_var.tests index d3ca25908..388d6a734 100755 --- a/shell/hush_test/hush-z_slow/leak_var.tests +++ b/shell/hush_test/hush-z_slow/leak_var.tests | |||
| @@ -1,24 +1,46 @@ | |||
| 1 | pid=$$ | 1 | pid=$$ |
| 2 | 2 | ||
| 3 | # Warm up | 3 | # Warm up |
| 4 | unset t | ||
| 5 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 6 | export t | ||
| 7 | unset t | ||
| 8 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 9 | export t | ||
| 10 | unset t | ||
| 11 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 12 | export t | ||
| 13 | unset t | ||
| 14 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 15 | export t | ||
| 16 | unset t | ||
| 17 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 18 | export t | ||
| 19 | i=1 | ||
| 20 | if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi | ||
| 21 | beg=`ps -o pid,vsz | grep "^ *$pid "` | 4 | beg=`ps -o pid,vsz | grep "^ *$pid "` |
| 5 | i=1 | ||
| 6 | while test $i != X; do | ||
| 7 | unset t | ||
| 8 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 9 | export t | ||
| 10 | unset t | ||
| 11 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 12 | export t | ||
| 13 | unset t | ||
| 14 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 15 | export t | ||
| 16 | unset t | ||
| 17 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 18 | export t | ||
| 19 | unset t | ||
| 20 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | ||
| 21 | export t | ||
| 22 | i=1$i | ||
| 23 | if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi | ||
| 24 | if test $i = 1111111111111111111111111111111111111111111112; then i=3; fi | ||
| 25 | if test $i = 1111111111111111111111111111111111111111111113; then i=4; fi | ||
| 26 | if test $i = 1111111111111111111111111111111111111111111114; then i=5; fi | ||
| 27 | if test $i = 1111111111111111111111111111111111111111111115; then i=6; fi | ||
| 28 | if test $i = 1111111111111111111111111111111111111111111116; then i=7; fi | ||
| 29 | if test $i = 1111111111111111111111111111111111111111111117; then i=8; fi | ||
| 30 | if test $i = 1111111111111111111111111111111111111111111118; then i=9; fi | ||
| 31 | if test $i = 1111111111111111111111111111111111111111111119; then i=a; fi | ||
| 32 | if test $i = 111111111111111111111111111111111111111111111a; then i=b; fi | ||
| 33 | if test $i = 111111111111111111111111111111111111111111111b; then i=c; fi | ||
| 34 | if test $i = 111111111111111111111111111111111111111111111c; then i=d; fi | ||
| 35 | if test $i = 111111111111111111111111111111111111111111111d; then i=e; fi | ||
| 36 | if test $i = 111111111111111111111111111111111111111111111e; then i=f; fi | ||
| 37 | if test $i = 111111111111111111111111111111111111111111111f; then i=g; fi | ||
| 38 | if test $i = 111111111111111111111111111111111111111111111g; then i=h; fi | ||
| 39 | if test $i = 111111111111111111111111111111111111111111111h; then i=i; fi | ||
| 40 | if test $i = 111111111111111111111111111111111111111111111i; then i=j; fi | ||
| 41 | if test $i = 111111111111111111111111111111111111111111111j; then i=X; fi | ||
| 42 | done | ||
| 43 | end=`ps -o pid,vsz | grep "^ *$pid "` | ||
| 22 | 44 | ||
| 23 | echo "Measuring memory leak..." | 45 | echo "Measuring memory leak..." |
| 24 | beg=`ps -o pid,vsz | grep "^ *$pid "` | 46 | beg=`ps -o pid,vsz | grep "^ *$pid "` |
diff --git a/shell/hush_test/run-all b/shell/hush_test/run-all index ec8323008..0d40ae6df 100755 --- a/shell/hush_test/run-all +++ b/shell/hush_test/run-all | |||
| @@ -31,6 +31,7 @@ do_test() | |||
| 31 | test -x "$x" || continue | 31 | test -x "$x" || continue |
| 32 | name="${x%%.tests}" | 32 | name="${x%%.tests}" |
| 33 | test -f "$name.right" || continue | 33 | test -f "$name.right" || continue |
| 34 | # echo Running test: "$name.right" | ||
| 34 | { | 35 | { |
| 35 | "$THIS_SH" "./$x" >"$name.xx" 2>&1 | 36 | "$THIS_SH" "./$x" >"$name.xx" 2>&1 |
| 36 | diff -u "$name.xx" "$name.right" >"../$1-$x.fail" && rm -f "$name.xx" "../$1-$x.fail" | 37 | diff -u "$name.xx" "$name.right" >"../$1-$x.fail" && rm -f "$name.xx" "../$1-$x.fail" |
