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 | |
parent | f23c3f95e88302923147f159115180da7cf0344e (diff) | |
download | busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.tar.gz busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.tar.bz2 busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.zip |
hush: plug memory leak
-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" |