From 072986823dc5304482015041de9e1643172eb1a0 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 19 Feb 2018 09:12:41 -0500 Subject: [PATCH] commit bash-20180216 snapshot --- COMPAT | 5 ++++ CWRU/CWRU.chlog | 63 +++++++++++++++++++++++++++++++++++++++++++++ Makefile.in | 6 ++--- builtins/evalfile.c | 4 ++- builtins/shopt.def | 10 +++++++ builtins/source.def | 2 ++ copy_cmd.c | 16 +++++++++--- doc/bash.1 | 14 ++++++++-- doc/bashref.texi | 9 +++++++ doc/version.texi | 6 ++--- execute_cmd.c | 5 ++++ shell.c | 33 +++++++++++++++++++----- shell.h | 1 + subst.c | 7 ++--- tests/coproc.tests | 4 +-- tests/history.right | 4 +-- tests/new-exp.right | 2 +- tests/shopt.right | 3 +++ variables.c | 22 ++++++++++++++++ variables.h | 2 ++ 20 files changed, 191 insertions(+), 27 deletions(-) diff --git a/COMPAT b/COMPAT index 9959b962..3ed6762e 100644 --- a/COMPAT +++ b/COMPAT @@ -451,6 +451,11 @@ compat43 set continue loops in the calling context. Bash-4.4 and later reset the loop state to prevent this. +compat44 set + - the shell sets up the values used by BASH_ARGV and BASH_ARGC so + they can expand to the shell's positional parameters even if extended + debug mode is not enabled + ------------------------------------------------------------------------------- Copying and distribution of this file, with or without modification, diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index bd8f7ce7..a99cbb67 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -14955,3 +14955,66 @@ jobs.c include/typemax.h - TYPE_MINIMUM, TYPE_MAXIMUM: updated definitions from coreutils-8.29, silences some compiler warnings + + 2/14 + ---- +Makefile.in + - maybe-clean: use cd and pwd -P to test whether or not two directory + names identical, since topdir = '.' and BUILD_DIR = full pathname + when you use something like `bash ./configure'. Problem reported by + Michael Felt + +subst.c + - split_at_delims: if SD_NOQUOTEDELIM is in the flags argument, don't + treat `'' and `"' as candidates for possible sequences of delimiters, + even if they're part of the delimiter set (the delims argument). + Fixes problem with completing lines like `foo --bar='quux baz' xx' + reported by Nick Patavalis + + 2/15 + ---- +copy_cmd.c + - copy_word_list: build the list in the right order, avoiding having + to reverse it at the end. Helps with long argument lists + +shell.c + - bind_args: build the argument list in the right order, avoiding + having to reverse it at the end. + - bind_args: only call push_args to save argc and argv as BASH_ARGC + and BASH_ARGV if debugging mode is enabled (debugging_mode != 0). + Inspired by report from Ambrose Feinstein + - bind_args: note that we've saved BASH_ARGC and BASH_ARGV by setting + bash_argv_initialized + - shell_reinitialize: reset bash_argv_initialized back to 0 so + BASH_ARGV and BASH_ARGC will be recreated if we're in debugging mode + +variables.c + - save_bash_argv: new function, initializes BASH_ARGV and BASH_ARGC + from the saved positional parameters + - init_bash_argv: initialize BASH_ARGV and BASH_ARGC if + bash_argv_initialized == 0 + +builtins/shopt.def + - shopt_set_debug_mode: if we're turning on debug mode, initialize + BASH_ARGC and BASH_ARGV if bash_argv_initialized == 0 + + 2/16 + ---- +execute_cmd.c + - execute_function: make sure BASH_ARGV and BASH_ARGC are initialized + before calling push_args (and before calling remember_args) + +builtins/source.def + - source_builtin: make sure BASH_ARGV and BASH_ARGC are initialized + before calling push_args (and before calling remember_args) + +builtins/evalfile.c + - _evalfile: if the shell compatibility level is 44 or lower, make + sure BASH_ARGV and BASH_ARGC are initialized before calling + array_push + +builtins/shopt.def + - compat44: new shell option. This will be the last compatXX option + +doc/{bash.1,bashref.texi} + - compat44: document new shell option diff --git a/Makefile.in b/Makefile.in index d62ea078..f86ebc1e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,6 @@ -# Makefile for bash-4.4, version 4.22 +# Makefile for bash-5.0, version 4.23 # -# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -914,7 +914,7 @@ maintainer-clean: basic-clean $(RM) $(CREATED_SUPPORT) Makefile pathnames.h maybe-clean: - -if test "X$(topdir)" != "X$(BUILD_DIR)" ; then \ + -if test X"`cd $(topdir) && pwd -P`" != X"`cd $(BUILD_DIR) && pwd -P`" ; then \ $(RM) parser-built y.tab.c y.tab.h ; \ fi diff --git a/builtins/evalfile.c b/builtins/evalfile.c index 4da8f52b..2c195e6a 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -254,7 +254,9 @@ file_error_and_exit: arguments */ if ((flags & FEVAL_NOPUSHARGS) == 0) { - array_push (bash_argv_a, (char *)filename); + if (shell_compatibility_level <= 44) + init_bash_argv (); + array_push (bash_argv_a, (char *)filename); /* XXX - unconditionally? */ tt[0] = '1'; tt[1] = '\0'; array_push (bash_argc_a, tt); if (flags & FEVAL_UNWINDPROT) diff --git a/builtins/shopt.def b/builtins/shopt.def index f01296ea..e51c5001 100644 --- a/builtins/shopt.def +++ b/builtins/shopt.def @@ -143,6 +143,7 @@ static int shopt_compat40; static int shopt_compat41; static int shopt_compat42; static int shopt_compat43; +static int shopt_compat44; typedef int shopt_set_func_t __P((char *, int)); @@ -174,6 +175,7 @@ static struct { { "compat41", &shopt_compat41, set_compatibility_level }, { "compat42", &shopt_compat42, set_compatibility_level }, { "compat43", &shopt_compat43, set_compatibility_level }, + { "compat44", &shopt_compat44, set_compatibility_level }, #if defined (READLINE) { "complete_fullquote", &complete_fullquote, (shopt_set_func_t *)NULL}, { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand }, @@ -578,6 +580,8 @@ shopt_set_debug_mode (option_name, mode) #if defined (DEBUGGER) error_trace_mode = function_trace_mode = debugging_mode; set_shellopts (); + if (debugging_mode) + init_bash_argv (); #endif return (0); } @@ -607,6 +611,7 @@ set_compatibility_level (option_name, mode) { shopt_compat31 = shopt_compat32 = 0; shopt_compat40 = shopt_compat41 = shopt_compat42 = shopt_compat43 = 0; + shopt_compat44 = 0; ind = find_shopt (option_name); *shopt_vars[ind].value = mode; } @@ -624,6 +629,8 @@ set_compatibility_level (option_name, mode) shell_compatibility_level = 42; else if (shopt_compat43) shell_compatibility_level = 43; + else if (shopt_compat44) + shell_compatibility_level = 44; else shell_compatibility_level = DEFAULT_COMPAT_LEVEL; @@ -642,10 +649,13 @@ set_compatibility_opts () { shopt_compat31 = shopt_compat32 = 0; shopt_compat40 = shopt_compat41 = shopt_compat42 = shopt_compat43 = 0; + shopt_compat44 = 0; switch (shell_compatibility_level) { case DEFAULT_COMPAT_LEVEL: break; + case 44: + shopt_compat44 = 1; break; case 43: shopt_compat43 = 1; break; case 42: diff --git a/builtins/source.def b/builtins/source.def index f5115eeb..bdd197fd 100644 --- a/builtins/source.def +++ b/builtins/source.def @@ -172,6 +172,8 @@ source_builtin (list) { push_dollar_vars (); add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL); + if (debugging_mode || shell_compatibility_level <= 44) + init_bash_argv (); /* Initialize BASH_ARGV and BASH_ARGC */ remember_args (list->next, 1); if (debugging_mode) push_args (list->next); /* Update BASH_ARGV and BASH_ARGC */ diff --git a/copy_cmd.c b/copy_cmd.c index d3ba7673..d2b5bc9c 100644 --- a/copy_cmd.c +++ b/copy_cmd.c @@ -69,12 +69,20 @@ WORD_LIST * copy_word_list (list) WORD_LIST *list; { - WORD_LIST *new_list; + WORD_LIST *new_list, *tl; - for (new_list = (WORD_LIST *)NULL; list; list = list->next) - new_list = make_word_list (copy_word (list->word), new_list); + for (new_list = tl = (WORD_LIST *)NULL; list; list = list->next) + { + if (new_list == 0) + new_list = tl = make_word_list (copy_word (list->word), new_list); + else + { + tl->next = make_word_list (copy_word (list->word), (WORD_LIST *)NULL); + tl = tl->next; + } + } - return (REVERSE_LIST (new_list, WORD_LIST *)); + return (new_list); } static PATTERN_LIST * diff --git a/doc/bash.1 b/doc/bash.1 index ea00f6bd..deecbe25 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -1498,7 +1498,9 @@ only when in extended debugging mode (see the description of the .B extdebug option to the .B shopt -builtin below) +builtin below). +Setting \fBextdebug\fP after the shell has started to execute a script +may result in inconsistent values. .TP .B BASH_ARGV An array variable containing all of the parameters in the current \fBbash\fP @@ -1516,7 +1518,9 @@ only when in extended debugging mode .B extdebug option to the .B shopt -builtin below) +builtin below). +Setting \fBextdebug\fP after the shell has started to execute a script +may result in inconsistent values. .TP .B BASH_ARGV0 When referenced, this variable expands to the name of the shell or shell @@ -9813,6 +9817,12 @@ and does not reset the loop state when a shell function is executed (this allows \fBbreak\fP or \fBcontinue\fP in a shell function to affect loops in the caller's context). .TP 8 +.B compat44 +If set, +.B bash +saves the positional parameters to BASH_ARGV and BASH_ARGC before they are +used, regardless of whether or not extended debugging mode is enabled. +.TP 8 .B complete_fullquote If set, .B bash diff --git a/doc/bashref.texi b/doc/bashref.texi index bc3c2649..2ba845ba 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -5198,6 +5198,11 @@ and does not reset the loop state when a shell function is executed (this allows @code{break} or @code{continue} in a shell function to affect loops in the caller's context). +@item compat44 +If set, Bash +saves the positional parameters to BASH_ARGV and BASH_ARGC before they are +used, regardless of whether or not extended debugging mode is enabled. + @item complete_fullquote If set, Bash quotes all shell metacharacters in filenames and directory names when @@ -5604,6 +5609,8 @@ The shell sets @code{BASH_ARGC} only when in extended debugging mode (see @ref{The Shopt Builtin} for a description of the @code{extdebug} option to the @code{shopt} builtin). +Setting @code{extdebug} after the shell has started to execute a script +may result in inconsistent values. @item BASH_ARGV An array variable containing all of the parameters in the current bash @@ -5615,6 +5622,8 @@ The shell sets @code{BASH_ARGV} only when in extended debugging mode (see @ref{The Shopt Builtin} for a description of the @code{extdebug} option to the @code{shopt} builtin). +Setting @code{extdebug} after the shell has started to execute a script +may result in inconsistent values. @item BASH_ARGV0 When referenced, this variable expands to the name of the shell or shell diff --git a/doc/version.texi b/doc/version.texi index bad22734..5d84d6ff 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,10 +2,10 @@ Copyright (C) 1988-2018 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Wed Jan 31 11:23:04 EST 2018 +@set LASTCHANGE Fri Feb 16 14:38:44 EST 2018 @set EDITION 4.4 @set VERSION 4.4 -@set UPDATED 31 January 2018 -@set UPDATED-MONTH January 2018 +@set UPDATED 16 February 2018 +@set UPDATED-MONTH February 2018 diff --git a/execute_cmd.c b/execute_cmd.c index f608429f..66d23540 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -4848,6 +4848,11 @@ execute_function (var, words, flags, fds_to_close, async, subshell) /* The temporary environment for a function is supposed to apply to all commands executed within the function body. */ + /* Initialize BASH_ARGC and BASH_ARGV before we blow away the positional + parameters */ + if (debugging_mode || shell_compatibility_level <= 44) + init_bash_argv (); + remember_args (words->next, 1); /* Update BASH_ARGV and BASH_ARGC */ diff --git a/shell.c b/shell.c index 0179e1e4..ad76636c 100644 --- a/shell.c +++ b/shell.c @@ -108,6 +108,7 @@ extern int gnu_error_format; /* Non-zero means that this shell has already been run; i.e. you should call shell_reinitialize () if you need to start afresh. */ int shell_initialized = 0; +int bash_argv_initialized = 0; COMMAND *global_command = (COMMAND *)NULL; @@ -1422,13 +1423,21 @@ bind_args (argv, arg_start, arg_end, start_index) int arg_start, arg_end, start_index; { register int i; - WORD_LIST *args; + WORD_LIST *args, *tl; + + for (i = arg_start, args = tl = (WORD_LIST *)NULL; i < arg_end; i++) + { + if (args == 0) + args = tl = make_word_list (make_word (argv[i]), args); + else + { + tl->next = make_word_list (make_word (argv[i]), (WORD_LIST *)NULL); + tl = tl->next; + } + } - for (i = arg_start, args = (WORD_LIST *)NULL; i < arg_end; i++) - args = make_word_list (make_word (argv[i]), args); if (args) { - args = REVERSE_LIST (args, WORD_LIST *); if (start_index == 0) /* bind to $0...$n for sh -c command */ { /* Posix.2 4.56.3 says that the first argument after sh -c command @@ -1437,12 +1446,23 @@ bind_args (argv, arg_start, arg_end, start_index) FREE (dollar_vars[0]); dollar_vars[0] = savestring (args->word->word); remember_args (args->next, 1); - push_args (args->next); /* BASH_ARGV and BASH_ARGC */ + if (debugging_mode) + { + push_args (args->next); /* BASH_ARGV and BASH_ARGC */ + bash_argv_initialized = 1; + } } else /* bind to $1...$n for shell script */ { remember_args (args, 1); - push_args (args); /* BASH_ARGV and BASH_ARGC */ + /* We do this unconditionally so something like -O extdebug doesn't + do it first. We're setting the definitive positional params + here. */ + if (debugging_mode) + { + push_args (args); /* BASH_ARGV and BASH_ARGC */ + bash_argv_initialized = 1; + } } dispose_words (args); @@ -1918,6 +1938,7 @@ shell_reinitialize () forced_interactive = interactive_shell = 0; subshell_environment = running_in_background = 0; expand_aliases = 0; + bash_argv_initialized = 0; /* XXX - should we set jobs_m_flag to 0 here? */ diff --git a/shell.h b/shell.h index ded8c3c7..80726052 100644 --- a/shell.h +++ b/shell.h @@ -99,6 +99,7 @@ extern int interactive, interactive_shell; extern int startup_state; extern int reading_shell_script; extern int shell_initialized; +extern int bash_argv_initialized; extern int subshell_environment; extern int current_command_number; extern int indirection_level; diff --git a/subst.c b/subst.c index 99cddf53..ffb69f29 100644 --- a/subst.c +++ b/subst.c @@ -2335,10 +2335,10 @@ split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp) /* If we're using IFS splitting, the non-whitespace delimiter char and any additional IFS whitespace delimits a field. */ if (ifs_split) - while (member (string[te], d) && spctabnl (string[te])) + while (member (string[te], d) && spctabnl (string[te]) && ((flags&SD_NOQUOTEDELIM) == 0 || (string[te] != '\'' && string[te] != '"'))) te++; else - while (member (string[te], d2)) + while (member (string[te], d2) && ((flags&SD_NOQUOTEDELIM) == 0 || (string[te] != '\'' && string[te] != '"'))) te++; } @@ -2371,7 +2371,8 @@ split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp) break; i = te; - while (member (string[i], d) && (ifs_split || spctabnl(string[i]))) + /* XXX - honor SD_NOQUOTEDELIM here */ + while (member (string[i], d) && (ifs_split || spctabnl(string[i])) && ((flags&SD_NOQUOTEDELIM) == 0 || (string[te] != '\'' && string[te] != '"'))) i++; if (string[i]) diff --git a/tests/coproc.tests b/tests/coproc.tests index d347eb74..5066f7c5 100644 --- a/tests/coproc.tests +++ b/tests/coproc.tests @@ -30,8 +30,8 @@ read LINE <&${REFLECT[0]} echo $LINE { sleep 1; kill $REFLECT_PID; } & -wait $REFLECT_PID >$TMPOUT 2>&1 || echo "coproc.tests: REFLECT: status $?" -grep 'Terminated.*coproc.*REFLECT' < $TMPOUT >/dev/null 2>&1 || { +wait $REFLECT_PID >$TMPOUT 2>&1 || { status=$? ; echo "coproc.tests: REFLECT: status $status" ; } +[[ $status < 128 || $status == 143 ]] || { echo "coproc.tests: wait for REFLECT failed" >&2 } rm -f $TMPOUT diff --git a/tests/history.right b/tests/history.right index 4a6c75ba..3bfa140b 100644 --- a/tests/history.right +++ b/tests/history.right @@ -140,9 +140,9 @@ three one two three -4.4 +5.0 echo ${BASH_VERSION%\.*} -4.4 +5.0 echo ${BASH_VERSION%\.*} a b diff --git a/tests/new-exp.right b/tests/new-exp.right index e95fa539..10d9c51b 100644 --- a/tests/new-exp.right +++ b/tests/new-exp.right @@ -623,7 +623,7 @@ c Sub = 0 2 4 8 <'ab cd'> <'4'> <'ab cd'> <> -argv[1] = +argv[1] = < > <' \t\n'> diff --git a/tests/shopt.right b/tests/shopt.right index cec6c2ab..bb0ac696 100644 --- a/tests/shopt.right +++ b/tests/shopt.right @@ -15,6 +15,7 @@ shopt -u compat40 shopt -u compat41 shopt -u compat42 shopt -u compat43 +shopt -u compat44 shopt -s complete_fullquote shopt -u direxpand shopt -u dirspell @@ -80,6 +81,7 @@ shopt -u compat40 shopt -u compat41 shopt -u compat42 shopt -u compat43 +shopt -u compat44 shopt -u direxpand shopt -u dirspell shopt -u dotglob @@ -120,6 +122,7 @@ compat40 off compat41 off compat42 off compat43 off +compat44 off direxpand off dirspell off dotglob off diff --git a/variables.c b/variables.c index e488b388..0c35105f 100644 --- a/variables.c +++ b/variables.c @@ -5088,6 +5088,28 @@ dispose_saved_dollar_vars () dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL; } +/* Initialize BASH_ARGV and BASH_ARGC after turning on extdebug after the + shell is initialized */ +void +init_bash_argv () +{ + if (bash_argv_initialized == 0) + { + save_bash_argv (); + bash_argv_initialized = 1; + } +} + +void +save_bash_argv () +{ + WORD_LIST *list; + + list = list_rest_of_args (); + push_args (list); + dispose_words (list); +} + /* Manipulate the special BASH_ARGV and BASH_ARGC variables. */ void diff --git a/variables.h b/variables.h index 777158cc..50d4ccb2 100644 --- a/variables.h +++ b/variables.h @@ -339,6 +339,8 @@ extern void push_dollar_vars __P((void)); extern void pop_dollar_vars __P((void)); extern void dispose_saved_dollar_vars __P((void)); +extern void init_bash_argv __P((void)); +extern void save_bash_argv __P((void)); extern void push_args __P((WORD_LIST *)); extern void pop_args __P((void));