hush: plug memory leak
This commit is contained in:
parent
f23c3f95e8
commit
f962a0354e
43
shell/hush.c
43
shell/hush.c
@ -144,6 +144,40 @@ static const char *indenter(int i)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Leak hunting. Use hush_leaktool.sh for post-processing.
|
||||||
|
*/
|
||||||
|
#ifdef FOR_HUSH_LEAKTOOL
|
||||||
|
void *xxmalloc(int lineno, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = xmalloc((size + 0xff) & ~0xff);
|
||||||
|
fprintf(stderr, "line %d: malloc %p\n", lineno, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
void *xxrealloc(int lineno, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
|
||||||
|
fprintf(stderr, "line %d: realloc %p\n", lineno, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
char *xxstrdup(int lineno, const char *str)
|
||||||
|
{
|
||||||
|
char *ptr = xstrdup(str);
|
||||||
|
fprintf(stderr, "line %d: strdup %p\n", lineno, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
void xxfree(void *ptr)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "free %p\n", ptr);
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
#define xmalloc(s) xxmalloc(__LINE__, s)
|
||||||
|
#define xrealloc(p, s) xxrealloc(__LINE__, p, s)
|
||||||
|
#define xstrdup(s) xxstrdup(__LINE__, s)
|
||||||
|
#define free(p) xxfree(p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if !ENABLE_HUSH_INTERACTIVE
|
#if !ENABLE_HUSH_INTERACTIVE
|
||||||
#undef ENABLE_FEATURE_EDITING
|
#undef ENABLE_FEATURE_EDITING
|
||||||
#define ENABLE_FEATURE_EDITING 0
|
#define ENABLE_FEATURE_EDITING 0
|
||||||
@ -256,7 +290,6 @@ struct child_prog {
|
|||||||
smallint subshell; /* flag, non-zero if group must be forked */
|
smallint subshell; /* flag, non-zero if group must be forked */
|
||||||
smallint is_stopped; /* is the program currently running? */
|
smallint is_stopped; /* is the program currently running? */
|
||||||
struct redir_struct *redirects; /* I/O redirections */
|
struct redir_struct *redirects; /* I/O redirections */
|
||||||
char **glob_result; /* result of parameter globbing */
|
|
||||||
struct pipe *family; /* pointer back to the child's parent pipe */
|
struct pipe *family; /* pointer back to the child's parent pipe */
|
||||||
//sp counting seems to be broken... so commented out, grep for '//sp:'
|
//sp counting seems to be broken... so commented out, grep for '//sp:'
|
||||||
//sp: int sp; /* number of SPECIAL_VAR_SYMBOL */
|
//sp: int sp; /* number of SPECIAL_VAR_SYMBOL */
|
||||||
@ -2198,8 +2231,8 @@ static int free_pipe(struct pipe *pi, int indent)
|
|||||||
for (a = 0, p = child->argv; *p; a++, p++) {
|
for (a = 0, p = child->argv; *p; a++, p++) {
|
||||||
debug_printf_clean("%s argv[%d] = %s\n", indenter(indent), a, *p);
|
debug_printf_clean("%s argv[%d] = %s\n", indenter(indent), a, *p);
|
||||||
}
|
}
|
||||||
free_strings(child->glob_result);
|
free_strings(child->argv);
|
||||||
child->glob_result = NULL;
|
child->argv = NULL;
|
||||||
} else if (child->group) {
|
} else if (child->group) {
|
||||||
debug_printf_clean("%s begin group (subshell:%d)\n", indenter(indent), child->subshell);
|
debug_printf_clean("%s begin group (subshell:%d)\n", indenter(indent), child->subshell);
|
||||||
ret_code = free_pipe_list(child->group, indent+3);
|
ret_code = free_pipe_list(child->group, indent+3);
|
||||||
@ -2333,6 +2366,7 @@ static int xglob(o_string *dest, char ***pglob)
|
|||||||
debug_printf("globhack returned %d\n", gr);
|
debug_printf("globhack returned %d\n", gr);
|
||||||
/* quote removal, or more accurately, backslash removal */
|
/* quote removal, or more accurately, backslash removal */
|
||||||
*pglob = globhack(dest->data, *pglob);
|
*pglob = globhack(dest->data, *pglob);
|
||||||
|
globfree(&globdata);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (gr != 0) { /* GLOB_ABORTED ? */
|
if (gr != 0) { /* GLOB_ABORTED ? */
|
||||||
@ -2340,7 +2374,6 @@ static int xglob(o_string *dest, char ***pglob)
|
|||||||
}
|
}
|
||||||
if (globdata.gl_pathv && globdata.gl_pathv[0])
|
if (globdata.gl_pathv && globdata.gl_pathv[0])
|
||||||
*pglob = add_strings_to_strings(1, *pglob, globdata.gl_pathv);
|
*pglob = add_strings_to_strings(1, *pglob, globdata.gl_pathv);
|
||||||
/* globprint(glob_target); */
|
|
||||||
globfree(&globdata);
|
globfree(&globdata);
|
||||||
return gr;
|
return gr;
|
||||||
}
|
}
|
||||||
@ -3001,6 +3034,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
|
|||||||
|
|
||||||
b_reset(dest);
|
b_reset(dest);
|
||||||
if (ctx->pending_redirect) {
|
if (ctx->pending_redirect) {
|
||||||
|
/* NB: don't free_strings(ctx->pending_redirect->glob_word) here */
|
||||||
if (ctx->pending_redirect->glob_word
|
if (ctx->pending_redirect->glob_word
|
||||||
&& ctx->pending_redirect->glob_word[0]
|
&& ctx->pending_redirect->glob_word[0]
|
||||||
&& ctx->pending_redirect->glob_word[1]
|
&& ctx->pending_redirect->glob_word[1]
|
||||||
@ -3056,7 +3090,6 @@ static int done_command(struct p_context *ctx)
|
|||||||
/*child->argv = NULL;*/
|
/*child->argv = NULL;*/
|
||||||
/*child->is_stopped = 0;*/
|
/*child->is_stopped = 0;*/
|
||||||
/*child->group = NULL;*/
|
/*child->group = NULL;*/
|
||||||
/*child->glob_result = NULL;*/
|
|
||||||
child->family = pi;
|
child->family = pi;
|
||||||
//sp: /*child->sp = 0;*/
|
//sp: /*child->sp = 0;*/
|
||||||
//pt: child->parse_type = ctx->parse_type;
|
//pt: child->parse_type = ctx->parse_type;
|
||||||
|
13
shell/hush_leaktool.sh
Normal file
13
shell/hush_leaktool.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# hush's stderr with leak debug enabled
|
||||||
|
output=output
|
||||||
|
|
||||||
|
freelist=`grep 'free 0x' "$output" | cut -d' ' -f2 | sort | uniq | xargs`
|
||||||
|
|
||||||
|
grep -v free "$output" >temp1
|
||||||
|
for freed in $freelist; do
|
||||||
|
echo Dropping $freed
|
||||||
|
cat temp1 | grep -v $freed >temp2
|
||||||
|
mv temp2 temp1
|
||||||
|
done
|
@ -1,24 +1,46 @@
|
|||||||
pid=$$
|
pid=$$
|
||||||
|
|
||||||
# Warm up
|
# Warm up
|
||||||
unset t
|
|
||||||
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
|
||||||
export t
|
|
||||||
unset t
|
|
||||||
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
|
||||||
export t
|
|
||||||
unset t
|
|
||||||
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
|
||||||
export t
|
|
||||||
unset t
|
|
||||||
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
|
||||||
export t
|
|
||||||
unset t
|
|
||||||
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
|
||||||
export t
|
|
||||||
i=1
|
|
||||||
if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi
|
|
||||||
beg=`ps -o pid,vsz | grep "^ *$pid "`
|
beg=`ps -o pid,vsz | grep "^ *$pid "`
|
||||||
|
i=1
|
||||||
|
while test $i != X; do
|
||||||
|
unset t
|
||||||
|
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
||||||
|
export t
|
||||||
|
unset t
|
||||||
|
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
||||||
|
export t
|
||||||
|
unset t
|
||||||
|
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
||||||
|
export t
|
||||||
|
unset t
|
||||||
|
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
||||||
|
export t
|
||||||
|
unset t
|
||||||
|
t=111111111111111111111111111111111111111111111111111111111111111111111111
|
||||||
|
export t
|
||||||
|
i=1$i
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111111; then i=2; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111112; then i=3; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111113; then i=4; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111114; then i=5; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111115; then i=6; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111116; then i=7; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111117; then i=8; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111118; then i=9; fi
|
||||||
|
if test $i = 1111111111111111111111111111111111111111111119; then i=a; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111a; then i=b; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111b; then i=c; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111c; then i=d; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111d; then i=e; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111e; then i=f; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111f; then i=g; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111g; then i=h; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111h; then i=i; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111i; then i=j; fi
|
||||||
|
if test $i = 111111111111111111111111111111111111111111111j; then i=X; fi
|
||||||
|
done
|
||||||
|
end=`ps -o pid,vsz | grep "^ *$pid "`
|
||||||
|
|
||||||
echo "Measuring memory leak..."
|
echo "Measuring memory leak..."
|
||||||
beg=`ps -o pid,vsz | grep "^ *$pid "`
|
beg=`ps -o pid,vsz | grep "^ *$pid "`
|
||||||
|
@ -31,6 +31,7 @@ do_test()
|
|||||||
test -x "$x" || continue
|
test -x "$x" || continue
|
||||||
name="${x%%.tests}"
|
name="${x%%.tests}"
|
||||||
test -f "$name.right" || continue
|
test -f "$name.right" || continue
|
||||||
|
# echo Running test: "$name.right"
|
||||||
{
|
{
|
||||||
"$THIS_SH" "./$x" >"$name.xx" 2>&1
|
"$THIS_SH" "./$x" >"$name.xx" 2>&1
|
||||||
diff -u "$name.xx" "$name.right" >"../$1-$x.fail" && rm -f "$name.xx" "../$1-$x.fail"
|
diff -u "$name.xx" "$name.right" >"../$1-$x.fail" && rm -f "$name.xx" "../$1-$x.fail"
|
||||||
|
Loading…
Reference in New Issue
Block a user