BASH PATCH REPORT ================= Bash-Release: 4.0 Patch-ID: bash40-044 Bug-Reported-by: Michal Zalewski Bug-Reference-ID: Bug-Reference-URL: Bug-Description: 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. Patch: *** ../bash-4.0.43/builtins/evalstring.c 2014-09-16 19:20:48.000000000 -0400 --- builtins/evalstring.c 2014-10-04 15:33:32.000000000 -0400 *************** *** 44,47 **** --- 44,48 ---- #include "../redir.h" #include "../trap.h" + #include "../bashintl.h" #include *************** *** 259,268 **** struct fd_bitmap *bitmap; ! if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def) { ! internal_warning ("%s: ignoring function definition attempt", from_file); ! should_jump_to_top_level = 0; ! last_result = last_command_exit_value = EX_BADUSAGE; ! break; } --- 260,282 ---- struct fd_bitmap *bitmap; ! if (flags & SEVAL_FUNCDEF) { ! 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; ! } } *************** *** 329,333 **** if (flags & SEVAL_ONECMD) ! break; } } --- 343,350 ---- if (flags & SEVAL_ONECMD) ! { ! reset_parser (); ! break; ! } } } *** ../bash-4.0.43/parse.y 2014-09-30 19:41:09.000000000 -0400 --- parse.y 2014-10-04 15:27:12.000000000 -0400 *************** *** 2279,2282 **** --- 2279,2292 ---- } + 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. */ *************** *** 3628,3633 **** restore_parser_state (&ps); reset_parser (); ! if (interactive) ! token_to_read = 0; /* Need to find how many characters parse_and_execute consumed, update --- 3638,3643 ---- restore_parser_state (&ps); reset_parser (); ! ! token_to_read = 0; /* Need to find how many characters parse_and_execute consumed, update *** ../bash-4.0.43/shell.h 2009-01-04 14:32:41.000000000 -0500 --- shell.h 2014-10-04 15:27:12.000000000 -0400 *************** *** 161,164 **** --- 161,166 ---- /* 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 *)); *** ../bash-4.0/patchlevel.h 2009-01-04 14:32:40.000000000 -0500 --- patchlevel.h 2009-02-22 16:11:31.000000000 -0500 *************** *** 26,30 **** looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 43 #endif /* _PATCHLEVEL_H_ */ --- 26,30 ---- looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 44 #endif /* _PATCHLEVEL_H_ */