From e298ce69baef029f3951dd1d5ed50fdbc6c55c80 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 4 Sep 2010 19:52:44 +0200 Subject: hush: fix handling of backslashes in variable assignment Signed-off-by: Denys Vlasenko --- shell/hush.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'shell/hush.c') diff --git a/shell/hush.c b/shell/hush.c index e8dfb2499..d3dab5863 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -390,6 +390,7 @@ typedef struct o_string { smallint o_glob; /* At least some part of the string was inside '' or "", * possibly empty one: word"", wo''rd etc. */ +//TODO: rename to no_empty_expansion? smallint o_quoted; smallint has_empty_slot; smallint o_assignment; /* 0:maybe, 1:yes, 2:no */ @@ -2018,11 +2019,10 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len { while (len) { o_addchr(o, *str); - if (*str++ == '\\' - && (*str != '*' && *str != '?' && *str != '[') - ) { + if (*str == '\\') { o_addchr(o, '\\'); } + str++; len--; } } @@ -2128,8 +2128,8 @@ static void debug_print_list(const char *prefix, o_string *o, int n) int i = 0; indent(); - fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d\n", - prefix, list, n, string_start, o->length, o->maxlen); + fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", + prefix, list, n, string_start, o->length, o->maxlen, o->o_glob, o->o_quoted, o->o_escape); while (i < n) { indent(); fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i], @@ -2563,9 +2563,9 @@ static char *expand_pseudo_dquoted(const char *str) struct in_str input; o_string dest = NULL_O_STRING; - if (strchr(str, '$') == NULL + if (!strchr(str, '$') #if ENABLE_HUSH_TICK - && strchr(str, '`') == NULL + && !strchr(str, '`') #endif ) { return NULL; @@ -2740,6 +2740,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char } #endif default: { /* varname */ +//TODO: move to a subroutine? char *var; char first_char; char exp_op; @@ -3000,18 +3001,22 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char return n; } -static char **expand_variables(char **argv, int or_mask) +enum { + EXPVAR_FLAG_GLOB = 0x200, + EXPVAR_FLAG_ESCAPE_VARS = 0x100, + EXPVAR_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ +}; +static char **expand_variables(char **argv, unsigned or_mask) { int n; char **list; char **v; o_string output = NULL_O_STRING; - if (or_mask & 0x100) { - output.o_escape = 1; /* protect against globbing for "$var" */ - /* (unquoted $var will temporarily switch it off) */ - output.o_glob = 1; - } + /* protect against globbing for "$var"? */ + /* (unquoted $var will temporarily switch it off) */ + output.o_escape = 1 & (or_mask / EXPVAR_FLAG_ESCAPE_VARS); + output.o_glob = 1 & (or_mask / EXPVAR_FLAG_GLOB); n = 0; v = argv; @@ -3029,13 +3034,13 @@ static char **expand_variables(char **argv, int or_mask) static char **expand_strvec_to_strvec(char **argv) { - return expand_variables(argv, 0x100); + return expand_variables(argv, EXPVAR_FLAG_GLOB | EXPVAR_FLAG_ESCAPE_VARS); } #if ENABLE_HUSH_BASH_COMPAT static char **expand_strvec_to_strvec_singleword_noglob(char **argv) { - return expand_variables(argv, 0x80); + return expand_variables(argv, EXPVAR_FLAG_SINGLEWORD); } #endif @@ -3075,15 +3080,15 @@ static char **expand_strvec_to_strvec_singleword_noglob_cond(char **argv) #endif /* Used for expansion of right hand of assignments */ -/* NB: should NOT do globbing! "export v=/bin/c*; env | grep ^v=" outputs - * "v=/bin/c*" */ +/* NB: should NOT do globbing! + * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*" */ static char *expand_string_to_string(const char *str) { char *argv[2], **list; argv[0] = (char*)str; argv[1] = NULL; - list = expand_variables(argv, 0x80); /* 0x80: singleword expansion */ + list = expand_variables(argv, EXPVAR_FLAG_ESCAPE_VARS | EXPVAR_FLAG_SINGLEWORD); if (HUSH_DEBUG) if (!list[0] || list[1]) bb_error_msg_and_die("BUG in varexp2"); @@ -3099,7 +3104,7 @@ static char* expand_strvec_to_string(char **argv) { char **list; - list = expand_variables(argv, 0x80); + list = expand_variables(argv, EXPVAR_FLAG_SINGLEWORD); /* Convert all NULs to spaces */ if (list[0]) { int n = 1; -- cgit v1.2.3