From 4d2700970a70cef98b157977ce40c4e0389cea44 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 19 Aug 2020 09:44:01 -0400 Subject: [PATCH] commit bash-20200814 snapshot --- CWRU/CWRU.chlog | 24 ++++++++++++++++++++++++ MANIFEST | 1 + bashhist.c | 4 ++-- command.h | 1 + subst.c | 31 +++++++++++++++++++++++++------ tests/new-exp.right | 11 +++++++++++ tests/new-exp.tests | 3 +++ tests/new-exp15.sub | 29 +++++++++++++++++++++++++++++ 8 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 tests/new-exp15.sub diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 3958e86d..f70b07fd 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8889,3 +8889,27 @@ flags.c {flags,variables}.c,flags.h,builtins/{declare,setattr.def} - no_invisible_vars: remove all references + +command.h + - PF_ALLINDS: new flag, means to expand an array variable name without + a subscript as if it were subscripted by `@' instead of `0' + +subst.c + - parameter_brace_expand_word: if PFLAGS contains PF_ALLINDS, expand + an array variable name as if it were subscripted by "@" instead of + 0/"0": a string with the element values separated by " ". Little + nuance; we're just interested in whether or not there are any + values at all + - parameter_brace_expand: if we are expanding something like ${foo@a}, + pass PF_ALLINDS to parameter_brace_expand_word and + parameter_brace_expand_indir so we don't get tripped up on `nounset' + if foo has an assigned subscript other than 0/"0". Inspired by a + report from Andrew Neff + + 8/17 + ---- +bashhist.c + - bash_add_history,maybe_add_history: don't need to call shell_comment + if we are in the middle of adding a here-document, since it may + call the parser recursively on data that is not guaranteed to be + valid input. From a report by Hyunho Cho diff --git a/MANIFEST b/MANIFEST index 78ee9cc6..f9a7af3a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1225,6 +1225,7 @@ tests/new-exp11.sub f tests/new-exp12.sub f tests/new-exp13.sub f tests/new-exp14.sub f +tests/new-exp15.sub f tests/new-exp.right f tests/nquote.tests f tests/nquote.right f diff --git a/bashhist.c b/bashhist.c index 7ccd4746..2a05a53f 100644 --- a/bashhist.c +++ b/bashhist.c @@ -757,7 +757,7 @@ maybe_add_history (line) int is_comment; hist_last_line_added = 0; - is_comment = shell_comment (line); + is_comment = (parser_state & PST_HEREDOC) ? 0 : shell_comment (line); /* Don't use the value of history_control to affect the second and subsequent lines of a multi-line command (old code did @@ -874,7 +874,7 @@ bash_add_history (line) add_it = 1; if (command_oriented_history && current_command_line_count > 1) { - is_comment = shell_comment (line); + is_comment = (parser_state & PST_HEREDOC) ? 0 : shell_comment (line); /* The second and subsequent lines of a here document have the trailing newline preserved. We don't want to add extra newlines here, but we diff --git a/command.h b/command.h index 12774c43..914198f9 100644 --- a/command.h +++ b/command.h @@ -113,6 +113,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, #define PF_ASSIGNRHS 0x08 /* same as W_ASSIGNRHS */ #define PF_COMPLETE 0x10 /* same as W_COMPLETE, sets SX_COMPLETE */ #define PF_EXPANDRHS 0x20 /* same as W_EXPANDRHS */ +#define PF_ALLINDS 0x40 /* array, act as if [@] was supplied */ /* Possible values for subshell_environment */ #define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */ diff --git a/subst.c b/subst.c index 32f842f3..300d4eb3 100644 --- a/subst.c +++ b/subst.c @@ -6823,7 +6823,15 @@ expand_arrayref: if (var_isset (var) && invisible_p (var) == 0) { #if defined (ARRAY_VARS) - if (assoc_p (var)) + /* We avoid a memory leak by saving TT as the memory allocated by + assoc_to_string or array_to_string and leaving it 0 otherwise, + then freeing TT after quoting temp. */ + tt = (char *)NULL; + if ((pflags & PF_ALLINDS) && assoc_p (var)) + tt = temp = assoc_empty (assoc_cell (var)) ? (char *)NULL : assoc_to_string (assoc_cell (var), " ", quoted); + else if ((pflags & PF_ALLINDS) && array_p (var)) + tt = temp = array_empty (array_cell (var)) ? (char *)NULL : array_to_string (array_cell (var), " ", quoted); + else if (assoc_p (var)) temp = assoc_reference (assoc_cell (var), "0"); else if (array_p (var)) temp = array_reference (array_cell (var), 0); @@ -6838,6 +6846,7 @@ expand_arrayref: ? quote_string (temp) : ((pflags & PF_ASSIGNRHS) ? quote_rhs (temp) : quote_escapes (temp)); + FREE (tt); } else temp = (char *)NULL; @@ -8772,17 +8781,18 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta int *indexp, quoted, pflags, *quoted_dollar_atp, *contains_dollar_at; { int check_nullness, var_is_set, var_is_null, var_is_special; - int want_substring, want_indir, want_patsub, want_casemod; + int want_substring, want_indir, want_patsub, want_casemod, want_attributes; char *name, *value, *temp, *temp1; WORD_DESC *tdesc, *ret; - int t_index, sindex, c, tflag, modspec, all_element_arrayref; + int t_index, sindex, c, tflag, modspec, local_pflags, all_element_arrayref; intmax_t number; arrayind_t ind; temp = temp1 = value = (char *)NULL; var_is_set = var_is_null = var_is_special = check_nullness = 0; - want_substring = want_indir = want_patsub = want_casemod = 0; + want_substring = want_indir = want_patsub = want_casemod = want_attributes = 0; + local_pflags = 0; all_element_arrayref = 0; sindex = *indexp; @@ -8876,6 +8886,12 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta want_casemod = 1; } #endif + else if (c == '@' && (string[sindex] == 'a' || string[sindex] == 'A') && string[sindex+1] == RBRACE) + { + /* special case because we do not want to shortcut foo as foo[0] here */ + want_attributes = 1; + local_pflags |= PF_ALLINDS; + } /* Catch the valid and invalid brace expressions that made it through the tests above. */ @@ -9043,7 +9059,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta if (want_indir) { - tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, pflags, quoted_dollar_atp, contains_dollar_at); + tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, pflags|local_pflags, quoted_dollar_atp, contains_dollar_at); if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal) { temp = (char *)NULL; @@ -9056,7 +9072,10 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta tdesc->flags &= ~W_ARRAYIND; } else - tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS)), &ind); + { + local_pflags |= PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS)); + tdesc = parameter_brace_expand_word (name, var_is_special, quoted, local_pflags, &ind); + } if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal) { diff --git a/tests/new-exp.right b/tests/new-exp.right index 9f378935..752bba5c 100644 --- a/tests/new-exp.right +++ b/tests/new-exp.right @@ -708,6 +708,17 @@ aaa bb 'a b' 'c d' 'e f' 0 "zero" 1 "one" 2 "two" 3 "three" 0 "zero z" 1 "one o" 2 "two t" 3 "three t" +declare -a foo=() +ai +declare -ai foo +bash: line 1: foo: unbound variable +ai +declare -ai foo +bash: line 1: !bar: unbound variable +a +a +a +a argv[1] = argv[1] = diff --git a/tests/new-exp.tests b/tests/new-exp.tests index 8d9ff8da..079426cb 100644 --- a/tests/new-exp.tests +++ b/tests/new-exp.tests @@ -628,6 +628,9 @@ ${THIS_SH} ./new-exp13.sub # new K parameter transformation operator ${THIS_SH} ./new-exp14.sub +# ongoing work with a/A parameter transformations and `nounset' +${THIS_SH} ./new-exp15.sub + # problems with stray CTLNUL in bash-4.0-alpha unset a a=/a diff --git a/tests/new-exp15.sub b/tests/new-exp15.sub new file mode 100644 index 00000000..f8b9ed84 --- /dev/null +++ b/tests/new-exp15.sub @@ -0,0 +1,29 @@ +# 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 . +# + +: ${THIS_SH:=./bash} + +${THIS_SH} -c 'declare -a foo=() ; declare -p foo' bash + +${THIS_SH} -c 'declare -ia foo=() ; echo ${foo@a} ; echo ${foo@A}' bash +${THIS_SH} -uc 'declare -ia foo=() ; echo ${foo@a} ; echo ${foo@A}' bash + +${THIS_SH} -c 'declare -ia foo=() ; bar=foo; echo ${!bar@a} ; echo ${!bar@A}' bash +${THIS_SH} -uc 'declare -ia foo=() ; bar=foo; echo ${!bar@a} ; echo ${!bar@A}' bash + +${THIS_SH} -c 'declare -a foo=( [1]=one ) ; echo ${foo@a}' bash +${THIS_SH} -uc 'declare -a foo=( [1]=one ) ; echo ${foo@a}' bash + +${THIS_SH} -c 'declare -a foo=( [1]=one ) ; bar=foo; echo ${!bar@a}' bash +${THIS_SH} -uc 'declare -a foo=( [1]=one ) ; bar=foo; echo ${!bar@a}' bash