aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c96
-rw-r--r--shell/hush_test/hush-misc/heredoc_huge.right3
-rwxr-xr-xshell/hush_test/hush-misc/heredoc_huge.tests9
-rw-r--r--shell/hush_test/hush-psubst/tick_huge.right3
-rwxr-xr-xshell/hush_test/hush-psubst/tick_huge.tests7
-rw-r--r--shell/hush_test/hush-z_slow/leak_all2.right3
-rwxr-xr-xshell/hush_test/hush-z_slow/leak_all2.tests87
7 files changed, 177 insertions, 31 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 4641dca11..9920e98c6 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2241,7 +2241,10 @@ static void re_execute_shell(const char *s, int is_heredoc)
2241 2241
2242 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); 2242 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
2243 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 2243 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
2244 execv(bb_busybox_exec_path, G.argv_from_re_execing); 2244 execve(bb_busybox_exec_path,
2245 G.argv_from_re_execing,
2246 (is_heredoc ? pp /* points to NULL ptr */ : environ)
2247 );
2245 /* Fallback. Useful for init=/bin/hush usage etc */ 2248 /* Fallback. Useful for init=/bin/hush usage etc */
2246 if (G.argv0_for_re_execing[0] == '/') 2249 if (G.argv0_for_re_execing[0] == '/')
2247 execv(G.argv0_for_re_execing, G.argv_from_re_execing); 2250 execv(G.argv0_for_re_execing, G.argv_from_re_execing);
@@ -4402,35 +4405,40 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
4402 4405
4403#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT 4406#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT
4404/* Subroutines for copying $(...) and `...` things */ 4407/* Subroutines for copying $(...) and `...` things */
4405static void add_till_backquote(o_string *dest, struct in_str *input); 4408static int add_till_backquote(o_string *dest, struct in_str *input);
4406/* '...' */ 4409/* '...' */
4407static void add_till_single_quote(o_string *dest, struct in_str *input) 4410static int add_till_single_quote(o_string *dest, struct in_str *input)
4408{ 4411{
4409 while (1) { 4412 while (1) {
4410 int ch = i_getch(input); 4413 int ch = i_getch(input);
4411 if (ch == EOF) 4414 if (ch == EOF) {
4412 break; 4415 syntax("unterminated '");
4416 return 1;
4417 }
4413 if (ch == '\'') 4418 if (ch == '\'')
4414 break; 4419 return 0;
4415 o_addchr(dest, ch); 4420 o_addchr(dest, ch);
4416 } 4421 }
4417} 4422}
4418/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ 4423/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
4419static void add_till_double_quote(o_string *dest, struct in_str *input) 4424static int add_till_double_quote(o_string *dest, struct in_str *input)
4420{ 4425{
4421 while (1) { 4426 while (1) {
4422 int ch = i_getch(input); 4427 int ch = i_getch(input);
4428 if (ch == EOF) {
4429 syntax("unterminated \"");
4430 return 1;
4431 }
4423 if (ch == '"') 4432 if (ch == '"')
4424 break; 4433 return 0;
4425 if (ch == '\\') { /* \x. Copy both chars. */ 4434 if (ch == '\\') { /* \x. Copy both chars. */
4426 o_addchr(dest, ch); 4435 o_addchr(dest, ch);
4427 ch = i_getch(input); 4436 ch = i_getch(input);
4428 } 4437 }
4429 if (ch == EOF)
4430 break;
4431 o_addchr(dest, ch); 4438 o_addchr(dest, ch);
4432 if (ch == '`') { 4439 if (ch == '`') {
4433 add_till_backquote(dest, input); 4440 if (add_till_backquote(dest, input))
4441 return 1;
4434 o_addchr(dest, ch); 4442 o_addchr(dest, ch);
4435 continue; 4443 continue;
4436 } 4444 }
@@ -4451,20 +4459,27 @@ static void add_till_double_quote(o_string *dest, struct in_str *input)
4451 * Example Output 4459 * Example Output
4452 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST 4460 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST
4453 */ 4461 */
4454static void add_till_backquote(o_string *dest, struct in_str *input) 4462static int add_till_backquote(o_string *dest, struct in_str *input)
4455{ 4463{
4456 while (1) { 4464 while (1) {
4457 int ch = i_getch(input); 4465 int ch = i_getch(input);
4466 if (ch == EOF) {
4467 syntax("unterminated `");
4468 return 1;
4469 }
4458 if (ch == '`') 4470 if (ch == '`')
4459 break; 4471 return 0;
4460 if (ch == '\\') { /* \x. Copy both chars unless it is \` */ 4472 if (ch == '\\') {
4473 /* \x. Copy both chars unless it is \` */
4461 int ch2 = i_getch(input); 4474 int ch2 = i_getch(input);
4475 if (ch2 == EOF) {
4476 syntax("unterminated `");
4477 return 1;
4478 }
4462 if (ch2 != '`' && ch2 != '$' && ch2 != '\\') 4479 if (ch2 != '`' && ch2 != '$' && ch2 != '\\')
4463 o_addchr(dest, ch); 4480 o_addchr(dest, ch);
4464 ch = ch2; 4481 ch = ch2;
4465 } 4482 }
4466 if (ch == EOF)
4467 break;
4468 o_addchr(dest, ch); 4483 o_addchr(dest, ch);
4469 } 4484 }
4470} 4485}
@@ -4480,13 +4495,15 @@ static void add_till_backquote(o_string *dest, struct in_str *input)
4480 * echo $(echo 'TEST)' BEST) TEST) BEST 4495 * echo $(echo 'TEST)' BEST) TEST) BEST
4481 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST 4496 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST
4482 */ 4497 */
4483static void add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl) 4498static int add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl)
4484{ 4499{
4485 int count = 0; 4500 int count = 0;
4486 while (1) { 4501 while (1) {
4487 int ch = i_getch(input); 4502 int ch = i_getch(input);
4488 if (ch == EOF) 4503 if (ch == EOF) {
4489 break; 4504 syntax("unterminated )");
4505 return 1;
4506 }
4490 if (ch == '(') 4507 if (ch == '(')
4491 count++; 4508 count++;
4492 if (ch == ')') { 4509 if (ch == ')') {
@@ -4501,23 +4518,29 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db
4501 } 4518 }
4502 o_addchr(dest, ch); 4519 o_addchr(dest, ch);
4503 if (ch == '\'') { 4520 if (ch == '\'') {
4504 add_till_single_quote(dest, input); 4521 if (add_till_single_quote(dest, input))
4522 return 1;
4505 o_addchr(dest, ch); 4523 o_addchr(dest, ch);
4506 continue; 4524 continue;
4507 } 4525 }
4508 if (ch == '"') { 4526 if (ch == '"') {
4509 add_till_double_quote(dest, input); 4527 if (add_till_double_quote(dest, input))
4528 return 1;
4510 o_addchr(dest, ch); 4529 o_addchr(dest, ch);
4511 continue; 4530 continue;
4512 } 4531 }
4513 if (ch == '\\') { /* \x. Copy verbatim. Important for \(, \) */ 4532 if (ch == '\\') {
4533 /* \x. Copy verbatim. Important for \(, \) */
4514 ch = i_getch(input); 4534 ch = i_getch(input);
4515 if (ch == EOF) 4535 if (ch == EOF) {
4516 break; 4536 syntax("unterminated )");
4537 return 1;
4538 }
4517 o_addchr(dest, ch); 4539 o_addchr(dest, ch);
4518 continue; 4540 continue;
4519 } 4541 }
4520 } 4542 }
4543 return 0;
4521} 4544}
4522#endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT */ 4545#endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT */
4523 4546
@@ -4658,7 +4681,8 @@ static int handle_dollar(o_string *as_string,
4658# if !BB_MMU 4681# if !BB_MMU
4659 pos = dest->length; 4682 pos = dest->length;
4660# endif 4683# endif
4661 add_till_closing_paren(dest, input, true); 4684 if (add_till_closing_paren(dest, input, true))
4685 return 1;
4662# if !BB_MMU 4686# if !BB_MMU
4663 if (as_string) { 4687 if (as_string) {
4664 o_addstr(as_string, dest->data + pos); 4688 o_addstr(as_string, dest->data + pos);
@@ -4671,20 +4695,19 @@ static int handle_dollar(o_string *as_string,
4671 } 4695 }
4672# endif 4696# endif
4673# if ENABLE_HUSH_TICK 4697# if ENABLE_HUSH_TICK
4674 //int pos = dest->length;
4675 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4698 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4676 o_addchr(dest, quote_mask | '`'); 4699 o_addchr(dest, quote_mask | '`');
4677# if !BB_MMU 4700# if !BB_MMU
4678 pos = dest->length; 4701 pos = dest->length;
4679# endif 4702# endif
4680 add_till_closing_paren(dest, input, false); 4703 if (add_till_closing_paren(dest, input, false))
4704 return 1;
4681# if !BB_MMU 4705# if !BB_MMU
4682 if (as_string) { 4706 if (as_string) {
4683 o_addstr(as_string, dest->data + pos); 4707 o_addstr(as_string, dest->data + pos);
4684 o_addchr(as_string, '`'); 4708 o_addchr(as_string, '`');
4685 } 4709 }
4686# endif 4710# endif
4687 //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
4688 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4711 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4689# endif 4712# endif
4690 break; 4713 break;
@@ -4778,7 +4801,8 @@ static int parse_stream_dquoted(o_string *as_string,
4778 //int pos = dest->length; 4801 //int pos = dest->length;
4779 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4802 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4780 o_addchr(dest, 0x80 | '`'); 4803 o_addchr(dest, 0x80 | '`');
4781 add_till_backquote(dest, input); 4804 if (add_till_backquote(dest, input))
4805 return 1;
4782 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4806 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4783 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); 4807 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
4784 goto again; 4808 goto again;
@@ -5043,10 +5067,20 @@ static struct pipe *parse_stream(char **pstring,
5043 break; 5067 break;
5044#if ENABLE_HUSH_TICK 5068#if ENABLE_HUSH_TICK
5045 case '`': { 5069 case '`': {
5046 //int pos = dest.length; 5070#if !BB_MMU
5071 int pos;
5072#endif
5047 o_addchr(&dest, SPECIAL_VAR_SYMBOL); 5073 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
5048 o_addchr(&dest, '`'); 5074 o_addchr(&dest, '`');
5049 add_till_backquote(&dest, input); 5075#if !BB_MMU
5076 pos = dest.length;
5077#endif
5078 if (add_till_backquote(&dest, input))
5079 goto parse_error;
5080#if !BB_MMU
5081 o_addstr(&ctx.as_string, dest.data + pos);
5082 o_addchr(&ctx.as_string, '`');
5083#endif
5050 o_addchr(&dest, SPECIAL_VAR_SYMBOL); 5084 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
5051 //debug_printf_subst("SUBST RES3 '%s'\n", dest.data + pos); 5085 //debug_printf_subst("SUBST RES3 '%s'\n", dest.data + pos);
5052 break; 5086 break;
diff --git a/shell/hush_test/hush-misc/heredoc_huge.right b/shell/hush_test/hush-misc/heredoc_huge.right
new file mode 100644
index 000000000..11740f674
--- /dev/null
+++ b/shell/hush_test/hush-misc/heredoc_huge.right
@@ -0,0 +1,3 @@
1546ed3f5c81c780d3ab86ada14824237 -
2546ed3f5c81c780d3ab86ada14824237 -
3End
diff --git a/shell/hush_test/hush-misc/heredoc_huge.tests b/shell/hush_test/hush-misc/heredoc_huge.tests
new file mode 100755
index 000000000..c2ec2817b
--- /dev/null
+++ b/shell/hush_test/hush-misc/heredoc_huge.tests
@@ -0,0 +1,9 @@
1# This creates 120k heredoc
2echo 'cat <<HERE | md5sum' >"$0.tmp"
3yes "123456789 123456789 123456789 123456789" | head -3000 >>"$0.tmp"
4echo 'HERE' >>"$0.tmp"
5
6yes "123456789 123456789 123456789 123456789" | head -3000 | md5sum
7. "$0.tmp"
8rm "$0.tmp"
9echo End
diff --git a/shell/hush_test/hush-psubst/tick_huge.right b/shell/hush_test/hush-psubst/tick_huge.right
new file mode 100644
index 000000000..11740f674
--- /dev/null
+++ b/shell/hush_test/hush-psubst/tick_huge.right
@@ -0,0 +1,3 @@
1546ed3f5c81c780d3ab86ada14824237 -
2546ed3f5c81c780d3ab86ada14824237 -
3End
diff --git a/shell/hush_test/hush-psubst/tick_huge.tests b/shell/hush_test/hush-psubst/tick_huge.tests
new file mode 100755
index 000000000..acce92fb2
--- /dev/null
+++ b/shell/hush_test/hush-psubst/tick_huge.tests
@@ -0,0 +1,7 @@
1# This creates 120k file
2yes "123456789 123456789 123456789 123456789" | head -3000 >>"$0.tmp"
3
4echo "`cat $0.tmp`" | md5sum
5rm "$0.tmp"
6yes "123456789 123456789 123456789 123456789" | head -3000 | md5sum
7echo End
diff --git a/shell/hush_test/hush-z_slow/leak_all2.right b/shell/hush_test/hush-z_slow/leak_all2.right
new file mode 100644
index 000000000..c6f0334f3
--- /dev/null
+++ b/shell/hush_test/hush-z_slow/leak_all2.right
@@ -0,0 +1,3 @@
1Warm up
2Measuring memory leak...
3Ok
diff --git a/shell/hush_test/hush-z_slow/leak_all2.tests b/shell/hush_test/hush-z_slow/leak_all2.tests
new file mode 100755
index 000000000..8fb1ca9b4
--- /dev/null
+++ b/shell/hush_test/hush-z_slow/leak_all2.tests
@@ -0,0 +1,87 @@
1# "Check many leaks" test #2
2# Cramming all kinds of weird commands in here.
3# As you find leaks, please create separate, small test
4# for each leak.
5# Narrowing down the leak using this large test may be difficult.
6# It is intended to be a blanket "is everything ok?" test
7
8echo "Warm up"
9local_var="local val"
10export dev_null="/dev/null"
11>$dev_null
12echo hi1 $local_var `echo ho` >>/dev/null
13echo hi2 $local_var </dev/null | echo 2>&- | cat 1<>/dev/null
14{ echo hi4 $local_var `echo ho` 1<>/dev/null; }
15( echo hi4 $local_var `echo ho` 1<>/dev/null )
16if echo $local_var; false
17 then echo not run
18 elif false <$dev_null
19 then none
20 else cat 0<>$dev_null 1<>"$dev_null"
21fi >>/dev/null
22{
23 if echo $local_var; then cat <<HERE
24Hi cat
25HERE
26 fi >>/dev/null
27} 1<>/dev/null
28while { echo $dev_null >>$dev_null; }; do cat <"$dev_null"; break; done
29( until { echo $dev_null >>$dev_null | false; }; do cat <"$dev_null"; break; done ) <$dev_null
30
31memleak
32
33echo "Measuring memory leak..."
34# Please copy the entire block from above verbatim
35local_var="local val"
36export dev_null="/dev/null"
37>$dev_null
38echo hi1 $local_var `echo ho` >>/dev/null
39echo hi2 $local_var </dev/null | echo 2>&- | cat 1<>/dev/null
40{ echo hi4 $local_var `echo ho` 1<>/dev/null; }
41( echo hi4 $local_var `echo ho` 1<>/dev/null )
42if echo $local_var; false
43 then echo not run
44 elif false <$dev_null
45 then none
46 else cat 0<>$dev_null 1<>"$dev_null"
47fi >>/dev/null
48{
49 if echo $local_var; then cat <<HERE
50Hi cat
51HERE
52 fi >>/dev/null
53} 1<>/dev/null
54while { echo $dev_null >>$dev_null; }; do cat <"$dev_null"; break; done
55( until { echo $dev_null >>$dev_null | false; }; do cat <"$dev_null"; break; done ) <$dev_null
56
57# And same again
58
59local_var="local val"
60export dev_null="/dev/null"
61>$dev_null
62echo hi1 $local_var `echo ho` >>/dev/null
63echo hi2 $local_var </dev/null | echo 2>&- | cat 1<>/dev/null
64{ echo hi4 $local_var `echo ho` 1<>/dev/null; }
65( echo hi4 $local_var `echo ho` 1<>/dev/null )
66if echo $local_var; false
67 then echo not run
68 elif false <$dev_null
69 then none
70 else cat 0<>$dev_null 1<>"$dev_null"
71fi >>/dev/null
72{
73 if echo $local_var; then cat <<HERE
74Hi cat
75HERE
76 fi >>/dev/null
77} 1<>/dev/null
78while { echo $dev_null >>$dev_null; }; do cat <"$dev_null"; break; done
79( until { echo $dev_null >>$dev_null | false; }; do cat <"$dev_null"; break; done ) <$dev_null
80
81memleak
82kb=$?
83if test $kb -le 4; then
84 echo Ok #$kb
85else
86 echo "Bad: $kb kb (or more) leaked"
87fi