aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-11-23 12:50:54 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-11-23 12:50:54 +0000
commitf962a0354e2426ef9781df97e4b02b32e438783c (patch)
tree4e0b3363932fbc0a30d5242b58ca5a0fea48d2a8
parentf23c3f95e88302923147f159115180da7cf0344e (diff)
downloadbusybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.tar.gz
busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.tar.bz2
busybox-w32-f962a0354e2426ef9781df97e4b02b32e438783c.zip
hush: plug memory leak
-rw-r--r--shell/hush.c43
-rw-r--r--shell/hush_leaktool.sh13
-rwxr-xr-xshell/hush_test/hush-z_slow/leak_var.tests56
-rwxr-xr-xshell/hush_test/run-all1
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
151void *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}
157void *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}
163char *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}
169void 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
4output=output
5
6freelist=`grep 'free 0x' "$output" | cut -d' ' -f2 | sort | uniq | xargs`
7
8grep -v free "$output" >temp1
9for freed in $freelist; do
10 echo Dropping $freed
11 cat temp1 | grep -v $freed >temp2
12 mv temp2 temp1
13done
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 @@
1pid=$$ 1pid=$$
2 2
3# Warm up 3# Warm up
4unset t
5t=111111111111111111111111111111111111111111111111111111111111111111111111
6export t
7unset t
8t=111111111111111111111111111111111111111111111111111111111111111111111111
9export t
10unset t
11t=111111111111111111111111111111111111111111111111111111111111111111111111
12export t
13unset t
14t=111111111111111111111111111111111111111111111111111111111111111111111111
15export t
16unset t
17t=111111111111111111111111111111111111111111111111111111111111111111111111
18export t
19i=1
20if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi
21beg=`ps -o pid,vsz | grep "^ *$pid "` 4beg=`ps -o pid,vsz | grep "^ *$pid "`
5i=1
6while 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
42done
43end=`ps -o pid,vsz | grep "^ *$pid "`
22 44
23echo "Measuring memory leak..." 45echo "Measuring memory leak..."
24beg=`ps -o pid,vsz | grep "^ *$pid "` 46beg=`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"