hush: fix var_bash5.tests failure
function old new delta expand_one_var 1513 1552 +39 expand_pseudo_dquoted 118 135 +17 expand_string_to_string 110 126 +16 setup_heredoc 298 308 +10 expand_and_evaluate_arith 69 79 +10 parse_stream_dquoted 233 241 +8 setup_redirects 220 225 +5 run_list 956 961 +5 expand_assignments 76 81 +5 run_pipe 1587 1590 +3 parse_stream 2371 2374 +3 builtin_umask 132 133 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 12/0 up/down: 122/0) Total: 122 bytes Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
parent
14e289b324
commit
ebee410fe2
43
shell/hush.c
43
shell/hush.c
@ -4335,7 +4335,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
/*** Execution routines ***/
|
/*** Execution routines ***/
|
||||||
|
|
||||||
/* Expansion can recurse, need forward decls: */
|
/* Expansion can recurse, need forward decls: */
|
||||||
static char *expand_string_to_string(const char *str);
|
static char *expand_string_to_string(const char *str, int do_unbackslash);
|
||||||
static int process_command_subs(o_string *dest, const char *s);
|
static int process_command_subs(o_string *dest, const char *s);
|
||||||
|
|
||||||
/* expand_strvec_to_strvec() takes a list of strings, expands
|
/* expand_strvec_to_strvec() takes a list of strings, expands
|
||||||
@ -4387,7 +4387,7 @@ static int expand_on_ifs(o_string *output, int n, const char *str)
|
|||||||
* Returns malloced string.
|
* Returns malloced string.
|
||||||
* As an optimization, we return NULL if expansion is not needed.
|
* As an optimization, we return NULL if expansion is not needed.
|
||||||
*/
|
*/
|
||||||
static char *expand_pseudo_dquoted(const char *str, int dquoted)
|
static char *expand_pseudo_dquoted(const char *str, int dquoted, int do_unbackslash)
|
||||||
{
|
{
|
||||||
char *exp_str;
|
char *exp_str;
|
||||||
struct in_str input;
|
struct in_str input;
|
||||||
@ -4408,7 +4408,7 @@ static char *expand_pseudo_dquoted(const char *str, int dquoted)
|
|||||||
setup_string_in_str(&input, str);
|
setup_string_in_str(&input, str);
|
||||||
parse_stream_dquoted(NULL, &dest, &input, EOF, dquoted);
|
parse_stream_dquoted(NULL, &dest, &input, EOF, dquoted);
|
||||||
//bb_error_msg("'%s' -> '%s'", str, dest.data);
|
//bb_error_msg("'%s' -> '%s'", str, dest.data);
|
||||||
exp_str = expand_string_to_string(dest.data);
|
exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash);
|
||||||
//bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
|
//bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
|
||||||
o_free_unsafe(&dest);
|
o_free_unsafe(&dest);
|
||||||
return exp_str;
|
return exp_str;
|
||||||
@ -4424,7 +4424,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p)
|
|||||||
hooks.lookupvar = get_local_var_value;
|
hooks.lookupvar = get_local_var_value;
|
||||||
hooks.setvar = set_local_var_from_halves;
|
hooks.setvar = set_local_var_from_halves;
|
||||||
//hooks.endofname = endofname;
|
//hooks.endofname = endofname;
|
||||||
exp_str = expand_pseudo_dquoted(arg, /*dquoted:*/ 1);
|
exp_str = expand_pseudo_dquoted(arg, /*dquoted:*/ 1, /*unbackslash:*/ 1);
|
||||||
res = arith(exp_str ? exp_str : arg, errcode_p, &hooks);
|
res = arith(exp_str ? exp_str : arg, errcode_p, &hooks);
|
||||||
free(exp_str);
|
free(exp_str);
|
||||||
return res;
|
return res;
|
||||||
@ -4594,8 +4594,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
//TODO: avoid xstrdup unless needed
|
//TODO: avoid xstrdup unless needed
|
||||||
// (see HACK ALERT below for an example)
|
// (see HACK ALERT below for an example)
|
||||||
val = to_be_freed = xstrdup(val);
|
val = to_be_freed = xstrdup(val);
|
||||||
//TODO: fix expansion rules:
|
exp_exp_word = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1, /*unbackslash:*/ 1);
|
||||||
exp_exp_word = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1);
|
|
||||||
if (exp_exp_word)
|
if (exp_exp_word)
|
||||||
exp_word = exp_exp_word;
|
exp_word = exp_exp_word;
|
||||||
loc = scan_and_match(to_be_freed, exp_word, scan_flags);
|
loc = scan_and_match(to_be_freed, exp_word, scan_flags);
|
||||||
@ -4631,9 +4630,8 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
* v='a bz'; echo ${v/a*z/\z} prints "z"
|
* v='a bz'; echo ${v/a*z/\z} prints "z"
|
||||||
* (note that a*z _pattern_ is never globbed!)
|
* (note that a*z _pattern_ is never globbed!)
|
||||||
*/
|
*/
|
||||||
//TODO: fix expansion rules:
|
|
||||||
char *pattern, *repl, *t;
|
char *pattern, *repl, *t;
|
||||||
pattern = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1);
|
pattern = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 0, /*unbackslash:*/ 0);
|
||||||
if (!pattern)
|
if (!pattern)
|
||||||
pattern = xstrdup(exp_word);
|
pattern = xstrdup(exp_word);
|
||||||
debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
|
debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
|
||||||
@ -4641,7 +4639,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
exp_word = p;
|
exp_word = p;
|
||||||
p = strchr(p, SPECIAL_VAR_SYMBOL);
|
p = strchr(p, SPECIAL_VAR_SYMBOL);
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
repl = expand_pseudo_dquoted(exp_word, /*dquoted:*/ arg0 & 0x80);
|
repl = expand_pseudo_dquoted(exp_word, /*dquoted:*/ arg0 & 0x80, /*unbackslash:*/ 1);
|
||||||
debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
|
debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
|
||||||
/* HACK ALERT. We depend here on the fact that
|
/* HACK ALERT. We depend here on the fact that
|
||||||
* G.global_argv and results of utoa and get_local_var_value
|
* G.global_argv and results of utoa and get_local_var_value
|
||||||
@ -4726,7 +4724,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
|
debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
|
||||||
(exp_save == ':') ? "true" : "false", use_word);
|
(exp_save == ':') ? "true" : "false", use_word);
|
||||||
if (use_word) {
|
if (use_word) {
|
||||||
to_be_freed = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1);
|
to_be_freed = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1, /*unbackslash:*/ 1);
|
||||||
if (to_be_freed)
|
if (to_be_freed)
|
||||||
exp_word = to_be_freed;
|
exp_word = to_be_freed;
|
||||||
if (exp_op == '?') {
|
if (exp_op == '?') {
|
||||||
@ -4998,30 +4996,35 @@ static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
|
|||||||
* NB: should NOT do globbing!
|
* NB: should NOT do globbing!
|
||||||
* "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
|
* "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
|
||||||
*/
|
*/
|
||||||
static char *expand_string_to_string(const char *str)
|
static char *expand_string_to_string(const char *str, int do_unbackslash)
|
||||||
{
|
{
|
||||||
char *argv[2], **list;
|
char *argv[2], **list;
|
||||||
|
|
||||||
|
debug_printf_expand("string_to_string<='%s'\n", str);
|
||||||
/* This is generally an optimization, but it also
|
/* This is generally an optimization, but it also
|
||||||
* handles "", which otherwise trips over !list[0] check below.
|
* handles "", which otherwise trips over !list[0] check below.
|
||||||
* (is this ever happens that we actually get str="" here?)
|
* (is this ever happens that we actually get str="" here?)
|
||||||
*/
|
*/
|
||||||
if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
|
if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
|
||||||
//TODO: Can use on strings with \ too, just unbackslash() them?
|
//TODO: Can use on strings with \ too, just unbackslash() them?
|
||||||
debug_printf_expand("string_to_string(fast)='%s'\n", str);
|
debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
|
||||||
return xstrdup(str);
|
return xstrdup(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[0] = (char*)str;
|
argv[0] = (char*)str;
|
||||||
argv[1] = NULL;
|
argv[1] = NULL;
|
||||||
list = expand_variables(argv, EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD);
|
list = expand_variables(argv, do_unbackslash
|
||||||
|
? EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD
|
||||||
|
: EXP_FLAG_SINGLEWORD
|
||||||
|
);
|
||||||
if (HUSH_DEBUG)
|
if (HUSH_DEBUG)
|
||||||
if (!list[0] || list[1])
|
if (!list[0] || list[1])
|
||||||
bb_error_msg_and_die("BUG in varexp2");
|
bb_error_msg_and_die("BUG in varexp2");
|
||||||
/* actually, just move string 2*sizeof(char*) bytes back */
|
/* actually, just move string 2*sizeof(char*) bytes back */
|
||||||
overlapping_strcpy((char*)list, list[0]);
|
overlapping_strcpy((char*)list, list[0]);
|
||||||
unbackslash((char*)list);
|
if (do_unbackslash)
|
||||||
debug_printf_expand("string_to_string='%s'\n", (char*)list);
|
unbackslash((char*)list);
|
||||||
|
debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
|
||||||
return (char*)list;
|
return (char*)list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5056,7 +5059,7 @@ static char **expand_assignments(char **argv, int count)
|
|||||||
G.expanded_assignments = p = NULL;
|
G.expanded_assignments = p = NULL;
|
||||||
/* Expand assignments into one string each */
|
/* Expand assignments into one string each */
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i]));
|
G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i], /*unbackslash:*/ 1));
|
||||||
}
|
}
|
||||||
G.expanded_assignments = NULL;
|
G.expanded_assignments = NULL;
|
||||||
return p;
|
return p;
|
||||||
@ -5465,7 +5468,7 @@ static void setup_heredoc(struct redir_struct *redir)
|
|||||||
|
|
||||||
expanded = NULL;
|
expanded = NULL;
|
||||||
if (!(redir->rd_dup & HEREDOC_QUOTED)) {
|
if (!(redir->rd_dup & HEREDOC_QUOTED)) {
|
||||||
expanded = expand_pseudo_dquoted(heredoc, /*dquoted:*/ 1);
|
expanded = expand_pseudo_dquoted(heredoc, /*dquoted:*/ 1, /*unbackslash:*/ 1);
|
||||||
if (expanded)
|
if (expanded)
|
||||||
heredoc = expanded;
|
heredoc = expanded;
|
||||||
}
|
}
|
||||||
@ -5565,7 +5568,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mode = redir_table[redir->rd_type].mode;
|
mode = redir_table[redir->rd_type].mode;
|
||||||
p = expand_string_to_string(redir->rd_filename);
|
p = expand_string_to_string(redir->rd_filename, /*unbackslash:*/ 1);
|
||||||
openfd = open_or_warn(p, mode);
|
openfd = open_or_warn(p, mode);
|
||||||
free(p);
|
free(p);
|
||||||
if (openfd < 0) {
|
if (openfd < 0) {
|
||||||
@ -6516,7 +6519,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
if (G_x_mode)
|
if (G_x_mode)
|
||||||
bb_putchar_stderr('+');
|
bb_putchar_stderr('+');
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
char *p = expand_string_to_string(*argv);
|
char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1);
|
||||||
if (G_x_mode)
|
if (G_x_mode)
|
||||||
fprintf(stderr, " %s", p);
|
fprintf(stderr, " %s", p);
|
||||||
debug_printf_exec("set shell var:'%s'->'%s'\n",
|
debug_printf_exec("set shell var:'%s'->'%s'\n",
|
||||||
@ -7020,7 +7023,7 @@ static int run_list(struct pipe *pi)
|
|||||||
/* all prev words didn't match, does this one match? */
|
/* all prev words didn't match, does this one match? */
|
||||||
argv = pi->cmds->argv;
|
argv = pi->cmds->argv;
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
char *pattern = expand_string_to_string(*argv);
|
char *pattern = expand_string_to_string(*argv, /*unbackslash:*/ 1);
|
||||||
/* TODO: which FNM_xxx flags to use? */
|
/* TODO: which FNM_xxx flags to use? */
|
||||||
cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
|
cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
|
||||||
free(pattern);
|
free(pattern);
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
a/
|
1 a/
|
||||||
a/d
|
2 a/d
|
||||||
a/e/f
|
3 a/e/f
|
||||||
|
4 a\
|
||||||
|
5 a\d
|
||||||
|
6 a\e\f
|
||||||
|
7 a\\
|
||||||
|
8 a\\d
|
||||||
|
9 a\\e\\f
|
||||||
|
a ab
|
||||||
Done: 0
|
Done: 0
|
||||||
|
@ -4,8 +4,26 @@
|
|||||||
v='a/b/c'
|
v='a/b/c'
|
||||||
s='b/c'
|
s='b/c'
|
||||||
r='e/f'
|
r='e/f'
|
||||||
echo "${v/$s}"
|
echo "1 ${v/$s}"
|
||||||
echo "${v/$s/d}"
|
echo "2 ${v/$s/d}"
|
||||||
echo "${v/$s/$r}"
|
echo "3 ${v/$s/$r}"
|
||||||
|
|
||||||
|
v='a\b\c'
|
||||||
|
s='b\\c'
|
||||||
|
r='e\f'
|
||||||
|
echo "4 ${v/$s}"
|
||||||
|
echo "5 ${v/$s/d}"
|
||||||
|
echo "6 ${v/$s/$r}"
|
||||||
|
|
||||||
|
v='a\\b\\c'
|
||||||
|
s='b\\\\c'
|
||||||
|
r='e\\f'
|
||||||
|
echo "7 ${v/$s}"
|
||||||
|
echo "8 ${v/$s/d}"
|
||||||
|
echo "9 ${v/$s/$r}"
|
||||||
|
|
||||||
|
v='a-$a-\t-\\-\"-\`-\--\z-\*-\?-b'
|
||||||
|
s='-$a-\\t-\\\\-\\"-\\`-\\--\\z-\\\*-\\\?-'
|
||||||
|
echo "a ${v/$s}"
|
||||||
|
|
||||||
echo Done: $?
|
echo Done: $?
|
||||||
|
Loading…
Reference in New Issue
Block a user