diff options
author | Michal Zalewski <lcamtuf@coredump.cx> | 2014-10-10 11:16:06 +0100 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2014-11-16 11:43:09 +0100 |
commit | 80df778bb8f868423dfe5fc9847238eee8d0a764 (patch) | |
tree | 59d45ed476618e369899aaf1252f5ffcbb4df87e | |
parent | 2190a70e6324494accf7747d2aa9f5e8702d875c (diff) | |
download | external_bash-80df778bb8f868423dfe5fc9847238eee8d0a764.zip external_bash-80df778bb8f868423dfe5fc9847238eee8d0a764.tar.gz external_bash-80df778bb8f868423dfe5fc9847238eee8d0a764.tar.bz2 |
bugfix: bash executing code following func defHEADreplicant-4.2-0004replicant-4.2-0003replicant-4.2
This is an upstream bugfix (with slight alterations):
Patch-ID: bash42-053
A combination of nested command substitutions and function importing from
the environment can cause bash to execute code appearing in the environment
variable value following the function definition.
Change-Id: I660e59c76d0d50de52d48a0d399fe1dfef3bded8
-rw-r--r-- | builtins/evalstring.c | 28 | ||||
-rw-r--r-- | parse.y | 14 | ||||
-rw-r--r-- | shell.h | 2 | ||||
-rw-r--r-- | y.tab.c | 13 |
4 files changed, 47 insertions, 10 deletions
diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 61f57fc..c2bce74 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -261,12 +261,25 @@ parse_and_execute (string, from_file, flags) { struct fd_bitmap *bitmap; - if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def) + if (flags & SEVAL_FUNCDEF) { - internal_warning ("%s: ignoring function definition attempt", from_file); - should_jump_to_top_level = 0; - last_result = last_command_exit_value = EX_BADUSAGE; - break; + char *x; + + /* If the command parses to something other than a straight + function definition, or if we have not consumed the entire + string, or if the parser has transformed the function + name (as parsing will if it begins or ends with shell + whitespace, for example), reject the attempt */ + if (command->type != cm_function_def || + ((x = parser_remaining_input ()) && *x) || + (STREQ (from_file, command->value.Function_def->name->word) == 0)) + { + internal_warning (_("%s: ignoring function definition attempt"), from_file); + should_jump_to_top_level = 0; + last_result = last_command_exit_value = EX_BADUSAGE; + reset_parser (); + break; + } } bitmap = new_fd_bitmap (FD_BITMAP_SIZE); @@ -331,7 +344,10 @@ parse_and_execute (string, from_file, flags) discard_unwind_frame ("pe_dispose"); if (flags & SEVAL_ONECMD) - break; + { + reset_parser (); + break; + } } } else @@ -2433,6 +2433,16 @@ shell_ungetc (c) eol_ungetc_lookahead = c; } +char * +parser_remaining_input () +{ + if (shell_input_line == 0) + return 0; + if (shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len) + return '\0'; /* XXX */ + return (shell_input_line + shell_input_line_index); +} + #ifdef INCLUDE_UNUSED /* Back the input pointer up by one, effectively `ungetting' a character. */ static void @@ -3883,8 +3893,8 @@ xparse_dolparen (base, string, indp, flags) restore_parser_state (&ps); reset_parser (); - if (interactive) - token_to_read = 0; + + token_to_read = 0; /* Need to find how many characters parse_and_execute consumed, update *indp, if flags != 0, copy the portion of the string parsed into RET @@ -167,5 +167,7 @@ typedef struct _sh_parser_state_t { } sh_parser_state_t; /* Let's try declaring these here. */ +extern char *parser_remaining_input __P((void)); + extern sh_parser_state_t *save_parser_state __P((sh_parser_state_t *)); extern void restore_parser_state __P((sh_parser_state_t *)); @@ -4746,6 +4746,16 @@ shell_ungetc (c) eol_ungetc_lookahead = c; } +char * +parser_remaining_input () +{ + if (shell_input_line == 0) + return 0; + if (shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len) + return '\0'; /* XXX */ + return (shell_input_line + shell_input_line_index); +} + #ifdef INCLUDE_UNUSED /* Back the input pointer up by one, effectively `ungetting' a character. */ static void @@ -6196,8 +6206,7 @@ xparse_dolparen (base, string, indp, flags) restore_parser_state (&ps); reset_parser (); - if (interactive) - token_to_read = 0; + token_to_read = 0; /* Need to find how many characters parse_and_execute consumed, update *indp, if flags != 0, copy the portion of the string parsed into RET |