hush: Don't parse the contents of a dereferenced var

When a variable which contains a user-supplied value is dereferenced
(e.g. to be echo'ed), make sure that the value is not further parsed
by hush.

Set the hush local variable "HUSH_NO_EVAL=1" to enable this behavior.

Without this patch, a sequence like this occurs:

	Panda # env set my_user_string Bob\'s favorite device
	Panda # print my_user_string
	my_user_string=Bob's favorite device
	Panda # echo $my_user_string
	syntax error hush.c:3007

With this patch, it looks like this:

	Panda # HUSH_NO_EVAL=1
	Panda # env set my_user_string Bob\'s favorite device
	Panda # print my_user_string
	my_user_string=Bob's favorite device
	Panda # echo $my_user_string
	Bob's favorite device

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
master
Joe Hershberger 12 years ago committed by Wolfgang Denk
parent 641b0d374e
commit a005f19eff
  1. 64
      common/hush.c

@ -127,6 +127,7 @@
#endif
#endif
#define SPECIAL_VAR_SYMBOL 03
#define SUBSTED_VAR_SYMBOL 04
#ifndef __U_BOOT__
#define FLAG_EXIT_FROM_LOOP 1
#define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */
@ -499,6 +500,7 @@ static void remove_bg_job(struct pipe *pi);
/* local variable support */
static char **make_list_in(char **inp, char *name);
static char *insert_var_value(char *inp);
static char *insert_var_value_sub(char *inp, int tag_subst);
#ifndef __U_BOOT__
/* Table of built-in functions. They can be forked or not, depending on
@ -3088,6 +3090,21 @@ int parse_stream(o_string *dest, struct p_context *ctx,
return 1;
break;
#endif
case SUBSTED_VAR_SYMBOL:
dest->nonnull = 1;
while (ch = b_getch(input), ch != EOF &&
ch != SUBSTED_VAR_SYMBOL) {
debug_printf("subst, pass=%d\n", ch);
if (input->__promptme == 0)
return 1;
b_addchr(dest, ch);
}
debug_printf("subst, term=%d\n", ch);
if (ch == EOF) {
syntax();
return 1;
}
break;
default:
syntax(); /* this is really an internal logic error */
return 1;
@ -3129,6 +3146,10 @@ void update_ifs_map(void)
mapset((uchar *)"\\$'\"`", 3); /* never flow through */
mapset((uchar *)"<>;&|(){}#", 1); /* flow through if quoted */
#else
{
uchar subst[2] = {SUBSTED_VAR_SYMBOL, 0};
mapset(subst, 3); /* never flow through */
}
mapset((uchar *)"\\$'\"", 3); /* never flow through */
mapset((uchar *)";&|#", 1); /* flow through if quoted */
#endif
@ -3468,25 +3489,57 @@ final_return:
static char *insert_var_value(char *inp)
{
return insert_var_value_sub(inp, 0);
}
static char *insert_var_value_sub(char *inp, int tag_subst)
{
int res_str_len = 0;
int len;
int done = 0;
char *p, *p1, *res_str = NULL;
while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
/* check the beginning of the string for normal charachters */
if (p != inp) {
/* copy any charachters to the result string */
len = p - inp;
res_str = xrealloc(res_str, (res_str_len + len));
strncpy((res_str + res_str_len), inp, len);
res_str_len += len;
}
inp = ++p;
/* find the ending marker */
p = strchr(inp, SPECIAL_VAR_SYMBOL);
*p = '\0';
/* look up the value to substitute */
if ((p1 = lookup_param(inp))) {
len = res_str_len + strlen(p1);
if (tag_subst)
len = res_str_len + strlen(p1) + 2;
else
len = res_str_len + strlen(p1);
res_str = xrealloc(res_str, (1 + len));
strcpy((res_str + res_str_len), p1);
if (tag_subst) {
/*
* copy the variable value to the result
* string
*/
strcpy((res_str + res_str_len + 1), p1);
/*
* mark the replaced text to be accepted as
* is
*/
res_str[res_str_len] = SUBSTED_VAR_SYMBOL;
res_str[res_str_len + 1 + strlen(p1)] =
SUBSTED_VAR_SYMBOL;
} else
/*
* copy the variable value to the result
* string
*/
strcpy((res_str + res_str_len), p1);
res_str_len = len;
}
*p = SPECIAL_VAR_SYMBOL;
@ -3550,9 +3603,14 @@ static char * make_string(char ** inp)
char *str = NULL;
int n;
int len = 2;
char *noeval_str;
int noeval = 0;
noeval_str = get_local_var("HUSH_NO_EVAL");
if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0')
noeval = 1;
for (n = 0; inp[n]; n++) {
p = insert_var_value(inp[n]);
p = insert_var_value_sub(inp[n], noeval);
str = xrealloc(str, (len + strlen(p)));
if (n) {
strcat(str, " ");

Loading…
Cancel
Save