aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-09-09 14:38:46 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-09-09 14:38:46 +0200
commitbfc02a76c5c3f0c8a5de518a46951098fef1e3cb (patch)
treeb2c789c55069acf0023cb31ac86737678f5b8c1f
parent101a4e3e2170e5ffa2bd2b06d7a71088a0ab8958 (diff)
downloadbusybox-w32-bfc02a76c5c3f0c8a5de518a46951098fef1e3cb.tar.gz
busybox-w32-bfc02a76c5c3f0c8a5de518a46951098fef1e3cb.tar.bz2
busybox-w32-bfc02a76c5c3f0c8a5de518a46951098fef1e3cb.zip
hush: fix a bug where expand_one_var wasn't restoring 1st char of the encoded $var
function old new delta expand_one_var 1515 1513 -2 expand_vars_to_list 1133 1122 -11 Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r--shell/hush.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/shell/hush.c b/shell/hush.c
index d58f526b8..9c615275c 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -4487,7 +4487,7 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c
4487/* Helper: 4487/* Helper:
4488 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. 4488 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
4489 */ 4489 */
4490static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp, char first_ch) 4490static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp)
4491{ 4491{
4492 const char *val = NULL; 4492 const char *val = NULL;
4493 char *to_be_freed = NULL; 4493 char *to_be_freed = NULL;
@@ -4498,11 +4498,13 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
4498 char exp_save = exp_save; /* for compiler */ 4498 char exp_save = exp_save; /* for compiler */
4499 char *exp_saveptr; /* points to expansion operator */ 4499 char *exp_saveptr; /* points to expansion operator */
4500 char *exp_word = exp_word; /* for compiler */ 4500 char *exp_word = exp_word; /* for compiler */
4501 char arg0;
4501 4502
4502 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */ 4503 *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
4503 var = arg; 4504 var = arg;
4504 exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL; 4505 exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
4505 first_char = arg[0] = first_ch & 0x7f; 4506 arg0 = arg[0];
4507 first_char = arg[0] = arg0 & 0x7f;
4506 exp_op = 0; 4508 exp_op = 0;
4507 4509
4508 if (first_char == '#' /* ${#... */ 4510 if (first_char == '#' /* ${#... */
@@ -4754,7 +4756,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
4754 *exp_saveptr = exp_save; 4756 *exp_saveptr = exp_save;
4755 } /* if (exp_op) */ 4757 } /* if (exp_op) */
4756 4758
4757 arg[0] = first_ch; 4759 arg[0] = arg0;
4758 4760
4759 *pp = p; 4761 *pp = p;
4760 *to_be_freed_pp = to_be_freed; 4762 *to_be_freed_pp = to_be_freed;
@@ -4771,11 +4773,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4771 /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in 4773 /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
4772 * expansion of right-hand side of assignment == 1-element expand. 4774 * expansion of right-hand side of assignment == 1-element expand.
4773 */ 4775 */
4774 char ored_ch; 4776 char cant_be_null = 0; /* only bit 0x80 matters */
4775 char *p; 4777 char *p;
4776 4778
4777 ored_ch = 0;
4778
4779 debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, 4779 debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
4780 !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); 4780 !!(output->o_expflags & EXP_FLAG_SINGLEWORD));
4781 debug_print_list("expand_vars_to_list", output, n); 4781 debug_print_list("expand_vars_to_list", output, n);
@@ -4797,11 +4797,17 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4797 arg = ++p; 4797 arg = ++p;
4798 p = strchr(p, SPECIAL_VAR_SYMBOL); 4798 p = strchr(p, SPECIAL_VAR_SYMBOL);
4799 4799
4800 /* Fetch special var name (if it is indeed one of them)
4801 * and quote bit, force the bit on if singleword expansion -
4802 * important for not getting v=$@ expand to many words. */
4800 first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD); 4803 first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
4801 /* "$@" is special. Even if quoted, it can still 4804
4802 * expand to nothing (not even an empty string) */ 4805 /* Is this variable quoted and thus expansion can't be null?
4806 * "$@" is special. Even if quoted, it can still
4807 * expand to nothing (not even an empty string),
4808 * thus it is excluded. */
4803 if ((first_ch & 0x7f) != '@') 4809 if ((first_ch & 0x7f) != '@')
4804 ored_ch |= first_ch; 4810 cant_be_null |= first_ch;
4805 4811
4806 switch (first_ch & 0x7f) { 4812 switch (first_ch & 0x7f) {
4807 /* Highest bit in first_ch indicates that var is double-quoted */ 4813 /* Highest bit in first_ch indicates that var is double-quoted */
@@ -4811,10 +4817,11 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4811 if (!G.global_argv[1]) 4817 if (!G.global_argv[1])
4812 break; 4818 break;
4813 i = 1; 4819 i = 1;
4814 ored_ch |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ 4820 cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
4815 if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ 4821 if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
4816 int sv = output->o_expflags; 4822 int sv = output->o_expflags;
4817 /* unquoted var's contents should be globbed, so don't escape */ 4823 /* unquoted var's contents should be globbed, so don't escape */
4824//TODO: make _caller_ set EXP_FLAG_ESC_GLOB_CHARS properly
4818 output->o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; 4825 output->o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
4819 while (G.global_argv[i]) { 4826 while (G.global_argv[i]) {
4820 n = expand_on_ifs(output, n, G.global_argv[i]); 4827 n = expand_on_ifs(output, n, G.global_argv[i]);
@@ -4833,7 +4840,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4833 /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....' 4840 /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
4834 * and in this case should treat it like '$*' - see 'else...' below */ 4841 * and in this case should treat it like '$*' - see 'else...' below */
4835 if (first_ch == ('@'|0x80) /* quoted $@ */ 4842 if (first_ch == ('@'|0x80) /* quoted $@ */
4836 && !(output->o_expflags & EXP_FLAG_SINGLEWORD) 4843 && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
4837 ) { 4844 ) {
4838 while (1) { 4845 while (1) {
4839 o_addQstr(output, G.global_argv[i]); 4846 o_addQstr(output, G.global_argv[i]);
@@ -4843,7 +4850,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4843 debug_print_list("expand_vars_to_list[4]", output, n); 4850 debug_print_list("expand_vars_to_list[4]", output, n);
4844 n = o_save_ptr(output, n); 4851 n = o_save_ptr(output, n);
4845 } 4852 }
4846 } else { /* quoted $*: add as one word */ 4853 } else { /* quoted $* (or v="$@" case): add as one word */
4847 while (1) { 4854 while (1) {
4848 o_addQstr(output, G.global_argv[i]); 4855 o_addQstr(output, G.global_argv[i]);
4849 if (!G.global_argv[++i]) 4856 if (!G.global_argv[++i])
@@ -4857,11 +4864,11 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4857 case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ 4864 case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
4858 /* "Empty variable", used to make "" etc to not disappear */ 4865 /* "Empty variable", used to make "" etc to not disappear */
4859 arg++; 4866 arg++;
4860 ored_ch = 0x80; 4867 cant_be_null = 0x80;
4861 break; 4868 break;
4862#if ENABLE_HUSH_TICK 4869#if ENABLE_HUSH_TICK
4863 case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */ 4870 case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
4864 *p = '\0'; 4871 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
4865 arg++; 4872 arg++;
4866 /* Can't just stuff it into output o_string, 4873 /* Can't just stuff it into output o_string,
4867 * expanded result may need to be globbed 4874 * expanded result may need to be globbed
@@ -4904,7 +4911,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4904 } 4911 }
4905#endif 4912#endif
4906 default: 4913 default:
4907 val = expand_one_var(&to_be_freed, arg, &p, first_ch); 4914 val = expand_one_var(&to_be_freed, arg, &p);
4908 IF_HUSH_TICK(store_val:) 4915 IF_HUSH_TICK(store_val:)
4909 if (!(first_ch & 0x80)) { /* unquoted $VAR */ 4916 if (!(first_ch & 0x80)) { /* unquoted $VAR */
4910 debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, 4917 debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
@@ -4912,6 +4919,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4912 if (val && val[0]) { 4919 if (val && val[0]) {
4913 /* unquoted var's contents should be globbed, so don't escape */ 4920 /* unquoted var's contents should be globbed, so don't escape */
4914 int sv = output->o_expflags; 4921 int sv = output->o_expflags;
4922//TODO: make _caller_ set EXP_FLAG_ESC_GLOB_CHARS properly
4915 output->o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; 4923 output->o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
4916 n = expand_on_ifs(output, n, val); 4924 n = expand_on_ifs(output, n, val);
4917 val = NULL; 4925 val = NULL;
@@ -4929,7 +4937,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4929 o_addQstr(output, val); 4937 o_addQstr(output, val);
4930 } 4938 }
4931 free(to_be_freed); 4939 free(to_be_freed);
4932 /* Do the check to avoid writing to a const string */ 4940
4941 /* Restore NULL'ed SPECIAL_VAR_SYMBOL.
4942 * Do the check to avoid writing to a const string. */
4933 if (*p != SPECIAL_VAR_SYMBOL) 4943 if (*p != SPECIAL_VAR_SYMBOL)
4934 *p = SPECIAL_VAR_SYMBOL; 4944 *p = SPECIAL_VAR_SYMBOL;
4935 4945
@@ -4946,7 +4956,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4946 o_addstr_with_NUL(output, arg); 4956 o_addstr_with_NUL(output, arg);
4947 debug_print_list("expand_vars_to_list[b]", output, n); 4957 debug_print_list("expand_vars_to_list[b]", output, n);
4948 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ 4958 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
4949 && !(ored_ch & 0x80) /* and all vars were not quoted. */ 4959 && !(cant_be_null & 0x80) /* and all vars were not quoted. */
4950 ) { 4960 ) {
4951 n--; 4961 n--;
4952 /* allow to reuse list[n] later without re-growth */ 4962 /* allow to reuse list[n] later without re-growth */