diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 21259d5b..99434a44 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8812,3 +8812,44 @@ jobs.c - start_job: don't allow `fg' or `bg' in a command substitution to attempt to start a parent's jobs. Suggested by OÄuz + +builtins/set.def + - set_current_options: only call change_flag or SET_BINARY_O_OPTION_VALUE + if the value has changed from what is stored in the bitmap, to avoid + any side effects from setting the options and save time on any + unnecessary function calls. Inspired by report from Grisha Levit + + +parse.y + - xparse_dolparen: before we jump to top level, check whether we are + still reading from the string (we might have run all the unwind- + protects) and turn off PST_CMDSUBST if we are not. Fixes fuzzing + bug reported by Jakub Wilk + + 8/4 + --- +subst.c + - process_substitute: set subshell_environment to include SUBSHELL_ASYNC + in the child process, since we passed FORK_ASYNC to make_child. Fixes + DEBUG trap problem reported by Jonathan Rascher + +subst.c + - unlink_all_fifos: new function, just unconditionally closes and + unlinks (if using FIFOs) each pipe used for process substitution. + There is an open to unblock any child processes sleeping on the + FIFO first. Inspired by a suggestion from "CHIGOT, CLEMENT" + + +shell.c + - exit_shell: call unlink_all_fifos() instead of unlink_fifo_list() + +sig.c + - termsig_handler: call unlink_all_fifos() instead of + unlink_fifo_list() + + 8/5 + --- +arrayfunc.c + - quote_compound_array_list: turn empty strings into '' instead of + leaving them unmodified. Fixes bug in changes from 4/29 reported + by andy_bash diff --git a/MANIFEST b/MANIFEST index d677ddda..78ee9cc6 100644 --- a/MANIFEST +++ b/MANIFEST @@ -916,6 +916,7 @@ tests/array24.sub f tests/array25.sub f tests/array26.sub f tests/array27.sub f +tests/array28.sub f tests/array-at-star f tests/array2.right f tests/assoc.tests f @@ -1457,6 +1458,7 @@ tests/varenv17.sub f tests/varenv18.sub f tests/varenv19.sub f tests/varenv20.sub f +tests/varenv21.sub f tests/version f tests/version.mini f tests/vredir.tests f diff --git a/arrayfunc.c b/arrayfunc.c index 6da71526..b254c85a 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -949,7 +949,8 @@ expand_and_quote_assoc_word (w, type) /* For each word in a compound array assignment, if the word looks like [ind]=value, single-quote ind and value, but leave the brackets and - the = sign (and any `+') alone. This is used for indexed arrays. */ + the = sign (and any `+') alone. If it's not an assignment, just single- + quote the word. This is used for indexed arrays. */ void quote_compound_array_list (list, type) WORD_LIST *list; @@ -960,7 +961,7 @@ quote_compound_array_list (list, type) for (l = list; l; l = l->next) { - if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0') + if (l->word == 0 || l->word->word == 0) continue; /* should not happen, but just in case... */ if ((l->word->flags & W_ASSIGNMENT) == 0) t = sh_single_quote (l->word->word); diff --git a/builtins/set.def b/builtins/set.def index 48927679..8ee01657 100644 --- a/builtins/set.def +++ b/builtins/set.def @@ -358,17 +358,29 @@ void set_current_options (bitmap) const char *bitmap; { - int i; + int i, v, cv, *on_or_off; if (bitmap == 0) return; for (i = 0; o_options[i].name; i++) { + v = bitmap[i] ? FLAG_ON : FLAG_OFF; if (o_options[i].letter) - change_flag (o_options[i].letter, bitmap[i] ? FLAG_ON : FLAG_OFF); + { + /* We should not get FLAG_UNKNOWN here */ + on_or_off = find_flag (o_options[i].letter); + cv = *on_or_off ? FLAG_ON : FLAG_OFF; + if (v != cv) + change_flag (o_options[i].letter, v); + } else - SET_BINARY_O_OPTION_VALUE (i, bitmap[i] ? FLAG_ON : FLAG_OFF, o_options[i].name); + { + cv = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name); + cv = cv ? FLAG_ON : FLAG_OFF; + if (v != cv) + SET_BINARY_O_OPTION_VALUE (i, v, o_options[i].name); + } } /* Now reset the variables changed by posix mode */ diff --git a/doc/bash.1 b/doc/bash.1 index 74617248..47a66610 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5,12 +5,12 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Tue Jun 16 16:24:30 EDT 2020 +.\" Last Change: Mon Aug 3 14:10:13 EDT 2020 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2020 June 16" "GNU Bash 5.1" +.TH BASH 1 "2020 August 3" "GNU Bash 5.1" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -8962,6 +8962,8 @@ If \fIname\fP is \-, the set of shell options is made local to the function in which \fBlocal\fP is invoked: shell options changed using the \fBset\fP builtin inside the function are restored to their original values when the function returns. +The restore is effected as if a series of \fBset\fP commands were executed +to restore the values that were in place before the function. With no operands, .B local writes a list of local variables to the standard output. It is diff --git a/doc/bashref.texi b/doc/bashref.texi index ce7a5e83..519d7a15 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -4440,6 +4440,8 @@ If @var{name} is @samp{-}, the set of shell options is made local to the function in which @code{local} is invoked: shell options changed using the @code{set} builtin inside the function are restored to their original values when the function returns. +The restore is effected as if a series of @code{set} commands were executed +to restore the values that were in place before the function. The return status is zero unless @code{local} is used outside a function, an invalid @var{name} is supplied, or @var{name} is a readonly variable. diff --git a/doc/version.texi b/doc/version.texi index 330f7867..5ef321f2 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,10 +2,11 @@ Copyright (C) 1988-2020 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Thu Jul 2 09:04:32 EDT 2020 +@set LASTCHANGE Mon Aug 3 14:09:53 EDT 2020 + @set EDITION 5.1 @set VERSION 5.1 -@set UPDATED 2 July 2020 -@set UPDATED-MONTH July 2020 +@set UPDATED 3 August 2020 +@set UPDATED-MONTH August 2020 diff --git a/lib/readline/readline.c b/lib/readline/readline.c index b706b605..800eb119 100644 --- a/lib/readline/readline.c +++ b/lib/readline/readline.c @@ -591,7 +591,6 @@ readline_internal_charloop (void) handler. */ if (c == READERR) { -fprintf(stderr, "rl_read_key returns READERR\r\n"); #if defined (READLINE_CALLBACKS) RL_SETSTATE(RL_STATE_DONE); return (rl_done = 1); diff --git a/parse.y b/parse.y index 25b42483..4b7363d6 100644 --- a/parse.y +++ b/parse.y @@ -4518,6 +4518,8 @@ xparse_dolparen (base, string, indp, flags) if (nc < 0) { clear_shell_input_line (); /* XXX */ + if (bash_input.type != st_string) /* paranoia */ + parser_state &= ~(PST_CMDSUBST|PST_EOFTOKEN); jump_to_top_level (-nc); /* XXX */ } diff --git a/shell.c b/shell.c index 7a579d1e..ce8087f7 100644 --- a/shell.c +++ b/shell.c @@ -981,7 +981,7 @@ exit_shell (s) s = run_exit_trap (); #if defined (PROCESS_SUBSTITUTION) - unlink_fifo_list (); + unlink_all_fifos (); #endif /* PROCESS_SUBSTITUTION */ #if defined (HISTORY) diff --git a/sig.c b/sig.c index 43f9e82a..44aa9939 100644 --- a/sig.c +++ b/sig.c @@ -593,7 +593,7 @@ termsig_handler (sig) #endif /* JOB_CONTROL */ #if defined (PROCESS_SUBSTITUTION) - unlink_fifo_list (); + unlink_all_fifos (); # if defined (JOB_CONTROL) procsub_clear (); # endif diff --git a/subst.c b/subst.c index 02006115..32f842f3 100644 --- a/subst.c +++ b/subst.c @@ -5365,8 +5365,11 @@ static void reap_some_procsubs PARAMS((int)); #if !defined (HAVE_DEV_FD) /* Named pipes must be removed explicitly with `unlink'. This keeps a list of FIFOs the shell has open. unlink_fifo_list will walk the list and - unlink all of them. add_fifo_list adds the name of an open FIFO to the - list. NFIFO is a count of the number of FIFOs in the list. */ + unlink the ones that don't have a living process on the other end. + unlink_all_fifos will walk the list and unconditionally unlink them, trying + to open and close the FIFO first to release any child processes sleeping on + the FIFO. add_fifo_list adds the name of an open FIFO to the list. + NFIFO is a count of the number of FIFOs in the list. */ #define FIFO_INCR 20 /* PROC value of -1 means the process has been reaped and the FIFO needs to @@ -5482,6 +5485,26 @@ unlink_fifo_list () nfifo = 0; } +void +unlink_all_fifos () +{ + int i, fd; + + if (nfifo == 0) + return; + + for (i = 0; i < nfifo; i++) + { + fifo_list[i].proc = (pid_t)-1; + fd = open (fifo_list[i].file, O_RDWR|O_NONBLOCK); + unlink_fifo (i); + if (fd >= 0) + close (fd); + } + + nfifo = 0; +} + /* Take LIST, which is a bitmap denoting active FIFOs in fifo_list from some point in the past, and close all open FIFOs in fifo_list that are not marked as active in LIST. If LIST is NULL, close @@ -5716,6 +5739,12 @@ unlink_fifo_list () nfds = 0; } +void +unlink_all_fifos () +{ + unlink_fifo_list (); +} + /* Take LIST, which is a snapshot copy of dev_fd_list from some point in the past, and close all open fds in dev_fd_list that are not marked as open in LIST. If LIST is NULL, close everything in dev_fd_list. @@ -5921,7 +5950,7 @@ process_substitute (string, open_for_read_in_child) setup_async_signals (); if (open_for_read_in_child == 0) async_redirect_stdin (); - subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB; + subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB|SUBSHELL_ASYNC; /* We don't inherit the verbose option for command substitutions now, so let's try it for process substitutions. */ diff --git a/subst.h b/subst.h index f7b29f02..13476515 100644 --- a/subst.h +++ b/subst.h @@ -270,6 +270,7 @@ extern char *pat_subst PARAMS((char *, char *, char *, int)); extern int fifos_pending PARAMS((void)); extern int num_fifos PARAMS((void)); extern void unlink_fifo_list PARAMS((void)); +extern void unlink_all_fifos PARAMS((void)); extern void unlink_fifo PARAMS((int)); extern void *copy_fifo_list PARAMS((int *)); diff --git a/support/bashbug.sh.in b/support/bashbug.sh.in index 5e92b995..d4b48c90 100644 --- a/support/bashbug.sh.in +++ b/support/bashbug.sh.in @@ -7,7 +7,7 @@ # chet@cwru.edu and, optionally, to bash-testers@cwru.edu. # Other versions send mail to bug-bash@gnu.org. # -# Copyright (C) 1996-2004 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 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 @@ -43,7 +43,7 @@ export PATH #Securely create a temporary directory for the temporary files TEMPDIR=$TMPDIR/bbug.$$ -(umask 077 && mkdir $TEMPDIR) || { +(umask 077 && mkdir "$TEMPDIR") || { echo "$0: could not create temporary directory" >&2 exit 1 } @@ -132,6 +132,8 @@ if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then DEFEDITOR=emacs elif [ -x /usr/bin/xemacs ]; then DEFEDITOR=xemacs + elif [ -x /usr/bin/nano ]; then + DEFEDITOR=nano elif [ -x /usr/contrib/bin/jove ]; then DEFEDITOR=jove elif [ -x /usr/local/bin/jove ]; then diff --git a/tests/array.right b/tests/array.right index dacfe951..2d1c51db 100644 --- a/tests/array.right +++ b/tests/array.right @@ -757,3 +757,9 @@ declare -A A=(["*"]="X" ["@"]="X" ) ./array27.sub: line 69: A[*]: bad array subscript ./array27.sub: line 69: A[@]: bad array subscript declare -A A +declare -a bug4=([0]="" [1]="5" [2]="" [3]="1" [4]="") +declare -a bug=([0]="" [1]="5" [2]="" [3]="1" [4]="") +declare -a bug2=([0]="") +declare -a bug3=([0]="" [1]="5" [2]="" [3]="1" [4]="") +declare -a not_bug=([0]="no" [1]="nulls") +declare -a workaround=([0]="") diff --git a/tests/array.tests b/tests/array.tests index d930e472..ba8e2254 100644 --- a/tests/array.tests +++ b/tests/array.tests @@ -424,3 +424,4 @@ ${THIS_SH} ./array24.sub ${THIS_SH} ./array25.sub ${THIS_SH} ./array26.sub ${THIS_SH} ./array27.sub +${THIS_SH} ./array28.sub diff --git a/tests/array28.sub b/tests/array28.sub new file mode 100644 index 00000000..e11cdb6d --- /dev/null +++ b/tests/array28.sub @@ -0,0 +1,30 @@ +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# tests for assigning empty string array elements without subscripts +function foo() +{ + local bug=("" "5" "" 1 "") + declare -a bug2=("") + declare -ga bug3=("" "5" "" 1 "") + local not_bug=("no" "nulls") + local workaround; workaround=("") + + declare -p bug bug2 bug3 not_bug workaround +} + +declare -a bug4=("" "5" "" 1 "") +declare -p bug4 + +foo diff --git a/tests/history4.sub b/tests/history4.sub index a6bfd33f..651374cf 100644 --- a/tests/history4.sub +++ b/tests/history4.sub @@ -14,6 +14,8 @@ HISTFILE=$TMPDIR/newhistory-$$ export HISTFILE +trap 'rm -f $HISTFILE' EXIT + HISTSIZE=32 HISTFILESIZE=32 echo @@ -43,4 +45,3 @@ echo printf "$input" | HISTSIZE= HISTFILE= ${THIS_SH} --norc -i 2>/dev/null echo printf "$input" | HISTSIZE=6 HISTFILE= ${THIS_SH} --norc -i 2>/dev/null - diff --git a/tests/varenv.right b/tests/varenv.right index 90f3efc7..358f5dc7 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -260,6 +260,11 @@ declare -x v="x" declare -x v="t" declare -- v declare -x v +ignoreeof on +ignoreeof off +ignoreeof on +10 +match 1 a=z a=b a=z diff --git a/tests/varenv.tests b/tests/varenv.tests index 42fb54db..b058ed4f 100644 --- a/tests/varenv.tests +++ b/tests/varenv.tests @@ -258,6 +258,7 @@ ${THIS_SH} ./varenv17.sub ${THIS_SH} ./varenv18.sub ${THIS_SH} ./varenv19.sub ${THIS_SH} ./varenv20.sub +${THIS_SH} ./varenv21.sub # make sure variable scoping is done right tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a diff --git a/tests/varenv21.sub b/tests/varenv21.sub new file mode 100644 index 00000000..613e4759 --- /dev/null +++ b/tests/varenv21.sub @@ -0,0 +1,48 @@ +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# test behavior of `local -' inside shell functions + +IGNOREEOF=0 +shopt -o ignoreeof + +f() +{ + local - + set +o ignoreeof + shopt -o ignoreeof +} + +f +shopt -o ignoreeof +echo $IGNOREEOF + +unset -f f + +f() +{ + local - + set -m -H +B + set -u +} + +before="$-|$SHELLOPTS" +f +after="$-|$SHELLOPTS" + +case "$after" in +$before) echo match 1 ;; +*) echo bad 1 ;; +esac + +unset -f f