diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-08 21:51:33 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-08 21:51:33 +0000 |
commit | 5c090a96f98f5a70af792945aa41ea53f82f39e2 (patch) | |
tree | 1a95c51f459436ca1e66157a708dbb34506e732c /shell/hush.c | |
parent | ffe6f8085170ed6a9780906374ca781e9c4291cb (diff) | |
download | busybox-w32-5c090a96f98f5a70af792945aa41ea53f82f39e2.tar.gz busybox-w32-5c090a96f98f5a70af792945aa41ea53f82f39e2.tar.bz2 busybox-w32-5c090a96f98f5a70af792945aa41ea53f82f39e2.zip |
hush: more rodust detection of unterminated strings etc;
fix a case where we forget to copy `cmd` text;
optimize nommu heredoc helper by not passing environment to it;
add several tests
function old new delta
add_till_closing_paren 256 308 +52
parse_stream 2337 2378 +41
add_till_backquote 82 111 +29
re_execute_shell 269 284 +15
handle_dollar 802 812 +10
parse_stream_dquoted 316 320 +4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/0 up/down: 151/0) Total: 151 bytes
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 96 |
1 files changed, 65 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 */ |
4405 | static void add_till_backquote(o_string *dest, struct in_str *input); | 4408 | static int add_till_backquote(o_string *dest, struct in_str *input); |
4406 | /* '...' */ | 4409 | /* '...' */ |
4407 | static void add_till_single_quote(o_string *dest, struct in_str *input) | 4410 | static 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? */ |
4419 | static void add_till_double_quote(o_string *dest, struct in_str *input) | 4424 | static 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 | */ |
4454 | static void add_till_backquote(o_string *dest, struct in_str *input) | 4462 | static 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 | */ |
4483 | static void add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl) | 4498 | static 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; |