diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-03 08:20:58 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-03 08:20:58 +0200 |
commit | 11752d46d18ff4a04a9f6736d129a82756a65a22 (patch) | |
tree | e75c6ab590a106d9933f135f4f8ea2c9dd40e44b | |
parent | f50e14632f7be56da7a38937c887f77812803f70 (diff) | |
download | busybox-w32-11752d46d18ff4a04a9f6736d129a82756a65a22.tar.gz busybox-w32-11752d46d18ff4a04a9f6736d129a82756a65a22.tar.bz2 busybox-w32-11752d46d18ff4a04a9f6736d129a82756a65a22.zip |
hush: one-word, no-globbing handling of local/export/readonly args
function old new delta
done_word 738 790 +52
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/shell/hush.c b/shell/hush.c index 867a921ec..184d720f5 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -79,20 +79,6 @@ | |||
79 | * Some builtins mandated by standards: | 79 | * Some builtins mandated by standards: |
80 | * newgrp [GRP]: not a builtin in bash but a suid binary | 80 | * newgrp [GRP]: not a builtin in bash but a suid binary |
81 | * which spawns a new shell with new group ID | 81 | * which spawns a new shell with new group ID |
82 | * In bash, export builtin is special, its arguments are assignments | ||
83 | * and therefore expansion of them should be "one-word" expansion: | ||
84 | * $ export i=`echo 'a b'` # export has one arg: "i=a b" | ||
85 | * compare with: | ||
86 | * $ ls i=`echo 'a b'` # ls has two args: "i=a" and "b" | ||
87 | * ls: cannot access i=a: No such file or directory | ||
88 | * ls: cannot access b: No such file or directory | ||
89 | * Note1: same applies to local builtin. | ||
90 | * Note2: bash 3.2.33(1) does this only if export word itself | ||
91 | * is not quoted: | ||
92 | * $ export i=`echo 'aaa bbb'`; echo "$i" | ||
93 | * aaa bbb | ||
94 | * $ "export" i=`echo 'aaa bbb'`; echo "$i" | ||
95 | * aaa | ||
96 | */ | 82 | */ |
97 | //config:config HUSH | 83 | //config:config HUSH |
98 | //config: bool "hush (64 kb)" | 84 | //config: bool "hush (64 kb)" |
@@ -630,8 +616,10 @@ struct command { | |||
630 | smallint cmd_type; /* CMD_xxx */ | 616 | smallint cmd_type; /* CMD_xxx */ |
631 | #define CMD_NORMAL 0 | 617 | #define CMD_NORMAL 0 |
632 | #define CMD_SUBSHELL 1 | 618 | #define CMD_SUBSHELL 1 |
633 | #if BASH_TEST2 | 619 | #if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY |
634 | /* used for "[[ EXPR ]]" */ | 620 | /* used for "[[ EXPR ]]", and to prevent word splitting and globbing in |
621 | * "export v=t*" | ||
622 | */ | ||
635 | # define CMD_SINGLEWORD_NOGLOB 2 | 623 | # define CMD_SINGLEWORD_NOGLOB 2 |
636 | #endif | 624 | #endif |
637 | #if ENABLE_HUSH_FUNCTIONS | 625 | #if ENABLE_HUSH_FUNCTIONS |
@@ -3933,14 +3921,37 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
3933 | (ctx->ctx_res_w == RES_SNTX)); | 3921 | (ctx->ctx_res_w == RES_SNTX)); |
3934 | return (ctx->ctx_res_w == RES_SNTX); | 3922 | return (ctx->ctx_res_w == RES_SNTX); |
3935 | } | 3923 | } |
3936 | # if BASH_TEST2 | 3924 | # if defined(CMD_SINGLEWORD_NOGLOB) |
3937 | if (strcmp(word->data, "[[") == 0) { | 3925 | if (0 |
3926 | # if BASH_TEST2 | ||
3927 | || strcmp(word->data, "[[") == 0 | ||
3928 | # endif | ||
3929 | /* In bash, local/export/readonly are special, args | ||
3930 | * are assignments and therefore expansion of them | ||
3931 | * should be "one-word" expansion: | ||
3932 | * $ export i=`echo 'a b'` # one arg: "i=a b" | ||
3933 | * compare with: | ||
3934 | * $ ls i=`echo 'a b'` # two args: "i=a" and "b" | ||
3935 | * ls: cannot access i=a: No such file or directory | ||
3936 | * ls: cannot access b: No such file or directory | ||
3937 | * Note: bash 3.2.33(1) does this only if export word | ||
3938 | * itself is not quoted: | ||
3939 | * $ export i=`echo 'aaa bbb'`; echo "$i" | ||
3940 | * aaa bbb | ||
3941 | * $ "export" i=`echo 'aaa bbb'`; echo "$i" | ||
3942 | * aaa | ||
3943 | */ | ||
3944 | IF_HUSH_LOCAL( || strcmp(word->data, "local") == 0) | ||
3945 | IF_HUSH_EXPORT( || strcmp(word->data, "export") == 0) | ||
3946 | IF_HUSH_READONLY( || strcmp(word->data, "readonly") == 0) | ||
3947 | ) { | ||
3938 | command->cmd_type = CMD_SINGLEWORD_NOGLOB; | 3948 | command->cmd_type = CMD_SINGLEWORD_NOGLOB; |
3939 | } | 3949 | } |
3940 | /* fall through */ | 3950 | /* fall through */ |
3941 | # endif | 3951 | # endif |
3942 | } | 3952 | } |
3943 | #endif | 3953 | #endif /* HAS_KEYWORDS */ |
3954 | |||
3944 | if (command->group) { | 3955 | if (command->group) { |
3945 | /* "{ echo foo; } echo bar" - bad */ | 3956 | /* "{ echo foo; } echo bar" - bad */ |
3946 | syntax_error_at(word->data); | 3957 | syntax_error_at(word->data); |
@@ -6299,7 +6310,7 @@ static char **expand_strvec_to_strvec(char **argv) | |||
6299 | return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); | 6310 | return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); |
6300 | } | 6311 | } |
6301 | 6312 | ||
6302 | #if BASH_TEST2 | 6313 | #if defined(CMD_SINGLEWORD_NOGLOB) |
6303 | static char **expand_strvec_to_strvec_singleword_noglob(char **argv) | 6314 | static char **expand_strvec_to_strvec_singleword_noglob(char **argv) |
6304 | { | 6315 | { |
6305 | return expand_variables(argv, EXP_FLAG_SINGLEWORD); | 6316 | return expand_variables(argv, EXP_FLAG_SINGLEWORD); |
@@ -8292,7 +8303,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8292 | } | 8303 | } |
8293 | 8304 | ||
8294 | /* Expand the rest into (possibly) many strings each */ | 8305 | /* Expand the rest into (possibly) many strings each */ |
8295 | #if BASH_TEST2 | 8306 | #if defined(CMD_SINGLEWORD_NOGLOB) |
8296 | if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { | 8307 | if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { |
8297 | argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); | 8308 | argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); |
8298 | } else | 8309 | } else |