diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-05-23 22:18:35 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-05-23 22:18:35 +0000 |
commit | bf7df04ec131c2d72e39d3ff6f2f85be675f9370 (patch) | |
tree | 6efda07961cb3432794453bb3842f04f2898c8bc | |
parent | 77d9268892b0d9624ab95bb551cbfe7a745d2666 (diff) | |
download | busybox-w32-bf7df04ec131c2d72e39d3ff6f2f85be675f9370.tar.gz busybox-w32-bf7df04ec131c2d72e39d3ff6f2f85be675f9370.tar.bz2 busybox-w32-bf7df04ec131c2d72e39d3ff6f2f85be675f9370.zip |
Fix a massive memory leak in the run_list_test() function.
Rename run_list_test() as free_pipe_list().
Rename run_pipe_test() as free_pipe().
-Erik
-rw-r--r-- | hush.c | 44 | ||||
-rw-r--r-- | shell/hush.c | 44 |
2 files changed, 22 insertions, 66 deletions
@@ -357,8 +357,8 @@ static void mark_closed(int fd); | |||
357 | static void close_all(); | 357 | static void close_all(); |
358 | /* "run" the final data structures: */ | 358 | /* "run" the final data structures: */ |
359 | static char *indenter(int i); | 359 | static char *indenter(int i); |
360 | static int run_list_test(struct pipe *head, int indent); | 360 | static int free_pipe_list(struct pipe *head, int indent); |
361 | static int run_pipe_test(struct pipe *pi, int indent); | 361 | static int free_pipe(struct pipe *pi, int indent); |
362 | /* really run the final data structures: */ | 362 | /* really run the final data structures: */ |
363 | static int setup_redirects(struct child_prog *prog, int squirrel[]); | 363 | static int setup_redirects(struct child_prog *prog, int squirrel[]); |
364 | static int pipe_wait(struct pipe *pi); | 364 | static int pipe_wait(struct pipe *pi); |
@@ -395,7 +395,6 @@ static int parse_file_outer(FILE *f); | |||
395 | static void checkjobs(); | 395 | static void checkjobs(); |
396 | static void insert_bg_job(struct pipe *pi); | 396 | static void insert_bg_job(struct pipe *pi); |
397 | static void remove_bg_job(struct pipe *pi); | 397 | static void remove_bg_job(struct pipe *pi); |
398 | static void free_pipe(struct pipe *pi); | ||
399 | /* local variable support */ | 398 | /* local variable support */ |
400 | static char *get_local_var(const char *var); | 399 | static char *get_local_var(const char *var); |
401 | static void unset_local_var(const char *name); | 400 | static void unset_local_var(const char *name); |
@@ -1138,7 +1137,7 @@ static void pseudo_exec(struct child_prog *child) | |||
1138 | debug_printf("runtime nesting to group\n"); | 1137 | debug_printf("runtime nesting to group\n"); |
1139 | interactive=0; /* crucial!!!! */ | 1138 | interactive=0; /* crucial!!!! */ |
1140 | rcode = run_list_real(child->group); | 1139 | rcode = run_list_real(child->group); |
1141 | /* OK to leak memory by not calling run_list_test, | 1140 | /* OK to leak memory by not calling free_pipe_list, |
1142 | * since this process is about to exit */ | 1141 | * since this process is about to exit */ |
1143 | _exit(rcode); | 1142 | _exit(rcode); |
1144 | } else { | 1143 | } else { |
@@ -1203,30 +1202,10 @@ static void remove_bg_job(struct pipe *pi) | |||
1203 | prev_pipe->next = pi->next; | 1202 | prev_pipe->next = pi->next; |
1204 | } | 1203 | } |
1205 | 1204 | ||
1206 | free_pipe(pi); | 1205 | free_pipe(pi, 0); |
1207 | free(pi); | 1206 | free(pi); |
1208 | } | 1207 | } |
1209 | 1208 | ||
1210 | /* free up all memory from a pipe */ | ||
1211 | static void free_pipe(struct pipe *pi) | ||
1212 | { | ||
1213 | int i; | ||
1214 | |||
1215 | for (i = 0; i < pi->num_progs; i++) { | ||
1216 | free(pi->progs[i].argv); | ||
1217 | if (pi->progs[i].redirects) | ||
1218 | free(pi->progs[i].redirects); | ||
1219 | } | ||
1220 | if (pi->progs) | ||
1221 | free(pi->progs); | ||
1222 | if (pi->text) | ||
1223 | free(pi->text); | ||
1224 | if (pi->cmdbuf) | ||
1225 | free(pi->cmdbuf); | ||
1226 | memset(pi, 0, sizeof(struct pipe)); | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | /* Checks to see if any background processes have exited -- if they | 1209 | /* Checks to see if any background processes have exited -- if they |
1231 | have, figure out why and see if a job has completed */ | 1210 | have, figure out why and see if a job has completed */ |
1232 | static void checkjobs() | 1211 | static void checkjobs() |
@@ -1535,7 +1514,7 @@ static char *indenter(int i) | |||
1535 | } | 1514 | } |
1536 | 1515 | ||
1537 | /* return code is the exit status of the pipe */ | 1516 | /* return code is the exit status of the pipe */ |
1538 | static int run_pipe_test(struct pipe *pi, int indent) | 1517 | static int free_pipe(struct pipe *pi, int indent) |
1539 | { | 1518 | { |
1540 | char **p; | 1519 | char **p; |
1541 | struct child_prog *child; | 1520 | struct child_prog *child; |
@@ -1554,7 +1533,7 @@ static int run_pipe_test(struct pipe *pi, int indent) | |||
1554 | child->argv=NULL; | 1533 | child->argv=NULL; |
1555 | } else if (child->group) { | 1534 | } else if (child->group) { |
1556 | final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); | 1535 | final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); |
1557 | ret_code = run_list_test(child->group,indent+3); | 1536 | ret_code = free_pipe_list(child->group,indent+3); |
1558 | final_printf("%s end group\n",ind); | 1537 | final_printf("%s end group\n",ind); |
1559 | } else { | 1538 | } else { |
1560 | final_printf("%s (nil)\n",ind); | 1539 | final_printf("%s (nil)\n",ind); |
@@ -1577,15 +1556,14 @@ static int run_pipe_test(struct pipe *pi, int indent) | |||
1577 | return ret_code; | 1556 | return ret_code; |
1578 | } | 1557 | } |
1579 | 1558 | ||
1580 | static int run_list_test(struct pipe *head, int indent) | 1559 | static int free_pipe_list(struct pipe *head, int indent) |
1581 | { | 1560 | { |
1582 | int rcode=0; /* if list has no members */ | 1561 | int rcode=0; /* if list has no members */ |
1583 | struct pipe *pi, *next; | 1562 | struct pipe *pi, *next; |
1584 | char *ind = indenter(indent); | 1563 | char *ind = indenter(indent); |
1585 | for (pi=head; pi; pi=next) { | 1564 | for (pi=head; pi; pi=next) { |
1586 | if (pi->num_progs == 0) break; | ||
1587 | final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); | 1565 | final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); |
1588 | rcode = run_pipe_test(pi, indent); | 1566 | rcode = free_pipe(pi, indent); |
1589 | final_printf("%s pipe followup code %d\n", ind, pi->followup); | 1567 | final_printf("%s pipe followup code %d\n", ind, pi->followup); |
1590 | next=pi->next; | 1568 | next=pi->next; |
1591 | pi->next=NULL; | 1569 | pi->next=NULL; |
@@ -1601,10 +1579,10 @@ static int run_list(struct pipe *pi) | |||
1601 | if (fake_mode==0) { | 1579 | if (fake_mode==0) { |
1602 | rcode = run_list_real(pi); | 1580 | rcode = run_list_real(pi); |
1603 | } | 1581 | } |
1604 | /* run_list_test has the side effect of clearing memory | 1582 | /* free_pipe_list has the side effect of clearing memory |
1605 | * In the long run that function can be merged with run_list_real, | 1583 | * In the long run that function can be merged with run_list_real, |
1606 | * but doing that now would hobble the debugging effort. */ | 1584 | * but doing that now would hobble the debugging effort. */ |
1607 | run_list_test(pi,0); | 1585 | free_pipe_list(pi,0); |
1608 | return rcode; | 1586 | return rcode; |
1609 | } | 1587 | } |
1610 | 1588 | ||
@@ -2142,7 +2120,7 @@ FILE *generate_stream_from_list(struct pipe *head) | |||
2142 | pf = fdopen(channel[0],"r"); | 2120 | pf = fdopen(channel[0],"r"); |
2143 | debug_printf("pipe on FILE *%p\n",pf); | 2121 | debug_printf("pipe on FILE *%p\n",pf); |
2144 | #else | 2122 | #else |
2145 | run_list_test(head,0); | 2123 | free_pipe_list(head,0); |
2146 | pf=popen("echo surrogate response","r"); | 2124 | pf=popen("echo surrogate response","r"); |
2147 | debug_printf("started fake pipe on FILE *%p\n",pf); | 2125 | debug_printf("started fake pipe on FILE *%p\n",pf); |
2148 | #endif | 2126 | #endif |
diff --git a/shell/hush.c b/shell/hush.c index 0dc2d62f8..57b85d1bc 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -357,8 +357,8 @@ static void mark_closed(int fd); | |||
357 | static void close_all(); | 357 | static void close_all(); |
358 | /* "run" the final data structures: */ | 358 | /* "run" the final data structures: */ |
359 | static char *indenter(int i); | 359 | static char *indenter(int i); |
360 | static int run_list_test(struct pipe *head, int indent); | 360 | static int free_pipe_list(struct pipe *head, int indent); |
361 | static int run_pipe_test(struct pipe *pi, int indent); | 361 | static int free_pipe(struct pipe *pi, int indent); |
362 | /* really run the final data structures: */ | 362 | /* really run the final data structures: */ |
363 | static int setup_redirects(struct child_prog *prog, int squirrel[]); | 363 | static int setup_redirects(struct child_prog *prog, int squirrel[]); |
364 | static int pipe_wait(struct pipe *pi); | 364 | static int pipe_wait(struct pipe *pi); |
@@ -395,7 +395,6 @@ static int parse_file_outer(FILE *f); | |||
395 | static void checkjobs(); | 395 | static void checkjobs(); |
396 | static void insert_bg_job(struct pipe *pi); | 396 | static void insert_bg_job(struct pipe *pi); |
397 | static void remove_bg_job(struct pipe *pi); | 397 | static void remove_bg_job(struct pipe *pi); |
398 | static void free_pipe(struct pipe *pi); | ||
399 | /* local variable support */ | 398 | /* local variable support */ |
400 | static char *get_local_var(const char *var); | 399 | static char *get_local_var(const char *var); |
401 | static void unset_local_var(const char *name); | 400 | static void unset_local_var(const char *name); |
@@ -1138,7 +1137,7 @@ static void pseudo_exec(struct child_prog *child) | |||
1138 | debug_printf("runtime nesting to group\n"); | 1137 | debug_printf("runtime nesting to group\n"); |
1139 | interactive=0; /* crucial!!!! */ | 1138 | interactive=0; /* crucial!!!! */ |
1140 | rcode = run_list_real(child->group); | 1139 | rcode = run_list_real(child->group); |
1141 | /* OK to leak memory by not calling run_list_test, | 1140 | /* OK to leak memory by not calling free_pipe_list, |
1142 | * since this process is about to exit */ | 1141 | * since this process is about to exit */ |
1143 | _exit(rcode); | 1142 | _exit(rcode); |
1144 | } else { | 1143 | } else { |
@@ -1203,30 +1202,10 @@ static void remove_bg_job(struct pipe *pi) | |||
1203 | prev_pipe->next = pi->next; | 1202 | prev_pipe->next = pi->next; |
1204 | } | 1203 | } |
1205 | 1204 | ||
1206 | free_pipe(pi); | 1205 | free_pipe(pi, 0); |
1207 | free(pi); | 1206 | free(pi); |
1208 | } | 1207 | } |
1209 | 1208 | ||
1210 | /* free up all memory from a pipe */ | ||
1211 | static void free_pipe(struct pipe *pi) | ||
1212 | { | ||
1213 | int i; | ||
1214 | |||
1215 | for (i = 0; i < pi->num_progs; i++) { | ||
1216 | free(pi->progs[i].argv); | ||
1217 | if (pi->progs[i].redirects) | ||
1218 | free(pi->progs[i].redirects); | ||
1219 | } | ||
1220 | if (pi->progs) | ||
1221 | free(pi->progs); | ||
1222 | if (pi->text) | ||
1223 | free(pi->text); | ||
1224 | if (pi->cmdbuf) | ||
1225 | free(pi->cmdbuf); | ||
1226 | memset(pi, 0, sizeof(struct pipe)); | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | /* Checks to see if any background processes have exited -- if they | 1209 | /* Checks to see if any background processes have exited -- if they |
1231 | have, figure out why and see if a job has completed */ | 1210 | have, figure out why and see if a job has completed */ |
1232 | static void checkjobs() | 1211 | static void checkjobs() |
@@ -1535,7 +1514,7 @@ static char *indenter(int i) | |||
1535 | } | 1514 | } |
1536 | 1515 | ||
1537 | /* return code is the exit status of the pipe */ | 1516 | /* return code is the exit status of the pipe */ |
1538 | static int run_pipe_test(struct pipe *pi, int indent) | 1517 | static int free_pipe(struct pipe *pi, int indent) |
1539 | { | 1518 | { |
1540 | char **p; | 1519 | char **p; |
1541 | struct child_prog *child; | 1520 | struct child_prog *child; |
@@ -1554,7 +1533,7 @@ static int run_pipe_test(struct pipe *pi, int indent) | |||
1554 | child->argv=NULL; | 1533 | child->argv=NULL; |
1555 | } else if (child->group) { | 1534 | } else if (child->group) { |
1556 | final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); | 1535 | final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); |
1557 | ret_code = run_list_test(child->group,indent+3); | 1536 | ret_code = free_pipe_list(child->group,indent+3); |
1558 | final_printf("%s end group\n",ind); | 1537 | final_printf("%s end group\n",ind); |
1559 | } else { | 1538 | } else { |
1560 | final_printf("%s (nil)\n",ind); | 1539 | final_printf("%s (nil)\n",ind); |
@@ -1577,15 +1556,14 @@ static int run_pipe_test(struct pipe *pi, int indent) | |||
1577 | return ret_code; | 1556 | return ret_code; |
1578 | } | 1557 | } |
1579 | 1558 | ||
1580 | static int run_list_test(struct pipe *head, int indent) | 1559 | static int free_pipe_list(struct pipe *head, int indent) |
1581 | { | 1560 | { |
1582 | int rcode=0; /* if list has no members */ | 1561 | int rcode=0; /* if list has no members */ |
1583 | struct pipe *pi, *next; | 1562 | struct pipe *pi, *next; |
1584 | char *ind = indenter(indent); | 1563 | char *ind = indenter(indent); |
1585 | for (pi=head; pi; pi=next) { | 1564 | for (pi=head; pi; pi=next) { |
1586 | if (pi->num_progs == 0) break; | ||
1587 | final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); | 1565 | final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); |
1588 | rcode = run_pipe_test(pi, indent); | 1566 | rcode = free_pipe(pi, indent); |
1589 | final_printf("%s pipe followup code %d\n", ind, pi->followup); | 1567 | final_printf("%s pipe followup code %d\n", ind, pi->followup); |
1590 | next=pi->next; | 1568 | next=pi->next; |
1591 | pi->next=NULL; | 1569 | pi->next=NULL; |
@@ -1601,10 +1579,10 @@ static int run_list(struct pipe *pi) | |||
1601 | if (fake_mode==0) { | 1579 | if (fake_mode==0) { |
1602 | rcode = run_list_real(pi); | 1580 | rcode = run_list_real(pi); |
1603 | } | 1581 | } |
1604 | /* run_list_test has the side effect of clearing memory | 1582 | /* free_pipe_list has the side effect of clearing memory |
1605 | * In the long run that function can be merged with run_list_real, | 1583 | * In the long run that function can be merged with run_list_real, |
1606 | * but doing that now would hobble the debugging effort. */ | 1584 | * but doing that now would hobble the debugging effort. */ |
1607 | run_list_test(pi,0); | 1585 | free_pipe_list(pi,0); |
1608 | return rcode; | 1586 | return rcode; |
1609 | } | 1587 | } |
1610 | 1588 | ||
@@ -2142,7 +2120,7 @@ FILE *generate_stream_from_list(struct pipe *head) | |||
2142 | pf = fdopen(channel[0],"r"); | 2120 | pf = fdopen(channel[0],"r"); |
2143 | debug_printf("pipe on FILE *%p\n",pf); | 2121 | debug_printf("pipe on FILE *%p\n",pf); |
2144 | #else | 2122 | #else |
2145 | run_list_test(head,0); | 2123 | free_pipe_list(head,0); |
2146 | pf=popen("echo surrogate response","r"); | 2124 | pf=popen("echo surrogate response","r"); |
2147 | debug_printf("started fake pipe on FILE *%p\n",pf); | 2125 | debug_printf("started fake pipe on FILE *%p\n",pf); |
2148 | #endif | 2126 | #endif |