minor changes for builtin array subscript expansion; additional tests

This commit is contained in:
Chet Ramey
2021-05-14 16:39:14 -04:00
parent a30f513fc4
commit 88bdb448b4
9 changed files with 220 additions and 10 deletions
+8
View File
@@ -10312,3 +10312,11 @@ subst.c
resulting WORD_LIST * as if special == 0, because we don't want to
quote the list for pattern matching. Report from
Adjudicator Darren <adjudicatordarren@protonmail.com>
5/14
----
subst.c
- expand_array_subscript: add double quote (") to the list of characters
that are backslash-quoted in subscripts after word expansion.
skipsubscript treats them specially, so you have to quote them to
do things like `key='"' ; array[$key]=1 ; [[ -v array[$key] ]]'
+1
View File
@@ -1314,6 +1314,7 @@ tests/quotearray1.sub f
tests/quotearray2.sub f
tests/quotearray3.sub f
tests/quotearray4.sub f
tests/quotearray5.sub f
tests/read.tests f
tests/read.right f
tests/read1.sub f
+1
View File
@@ -10199,6 +10199,7 @@ expand_array_subscript (string, sindex, quoted, flags)
abstab[LBRACK] = abstab[RBRACK] = 1;
abstab['$'] = abstab['`'] = abstab['~'] = 1;
abstab['\\'] = abstab['\''] = 1;
abstab['"'] = 1; /* XXX */
/* We don't quote `@' or `*' in the subscript at all. */
}
+41 -10
View File
@@ -21,17 +21,17 @@ declare -A A=(["~"]="43" ["~0"]="43" )
declare -a a=([0]="12" [1]="42")
2
2
declare -Ai assoc=(["']"]="2" ["\$var"]="1" )
declare -Ai assoc=(["']"]="3" ["\$var"]="1" )
105
declare -A assoc=(["\` echo >&2 foo\`"]="42" ["\$( echo >&2 bar)"]="63" )
./quotearray.tests: line 139: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
./quotearray.tests: line 143: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
./quotearray.tests: line 140: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
./quotearray.tests: line 144: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
1
./quotearray.tests: line 146: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
./quotearray.tests: line 147: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
1
./quotearray.tests: line 149: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
./quotearray.tests: line 150: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
1
./quotearray.tests: line 152: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
./quotearray.tests: line 153: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
1
declare -A assoc
0
@@ -57,8 +57,11 @@ foo
0
1
1
./quotearray1.sub: line 111: test: aa[$(echo: binary operator expected
./quotearray1.sub: line 113: test: aa[$(echo: binary operator expected
2
[[ -v assoc[a] ]]; $?=0
[[ -v assoc["] ]]; $?=0
declare -A assoc=(["\""]="123" [a]="123" )
declare -A a=([1]="1" [0]="0" [" "]="11" )
7
7
@@ -80,18 +83,23 @@ declare -A assoc=(["\$var"]="value" )
declare -A assoc=(["\$var"]="value" )
declare -A assoc=(["\$var"]="value" )
declare -A assoc=()
declare -A a=()
declare -A a=(["\$(echo foo)"]="1" )
declare -A a=()
declare -A a=(["\$(echo foo)"]="1" )
declare -A a=(["\$(echo foo)"]="1" )
declare -A assoc=(["!"]="bang" )
1
1
declare -A assoc=(["!"]="bang" ["@"]="at" )
declare -A assoc=(["!"]="bang" )
declare -a array=([0]="1" [1]="2" [2]="3")
./quotearray3.sub: line 93: declare: array: not found
./quotearray3.sub: line 97: declare: array: not found
./quotearray3.sub: line 94: declare: array: not found
./quotearray3.sub: line 98: declare: array: not found
declare -A map=(["foo\$(uname >/dev/tty)bar"]="1" )
1
declare -A map=()
$(DOESNOTEXIST)
declare -A blah=()
declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]="at" )
declare -A assoc=(["*"]="star" ["!"]="bang" )
declare -A assoc=(["!"]="bang" )
@@ -119,3 +127,26 @@ declare -a array=([0]="1" [1]="2" [2]="3")
0
./quotearray4.sub: line 115: array[@]: bad array subscript
declare -a array=([0]="1" [1]="2" [2]="3")
./quotearray5.sub: line 27: unset: `a[$(echo': not a valid identifier
./quotearray5.sub: line 27: unset: `foo)]': not a valid identifier
declare -A a=()
declare -A a=()
declare -A a=()
-----
declare -A a=(["\$(echo foo)"]="1" )
declare -A a=()
declare -A a=()
declare -A a=()
-----
declare -A a=()
declare -A a=()
declare -A a=()
----------
declare -A a=([.]="v1" )
declare -A a=([.]="v1" )
-----
declare -A a=([.]="v1" )
declare -A a=([.]="v1" )
-----
declare -A a=([.]="v1" )
declare -A a=([.]="v1" )
+4
View File
@@ -119,6 +119,7 @@ declare -Ai assoc
assoc[$var]=1
assoc[$var]+=1
((assoc['$var']++))
((assoc[$var]++))
typeset -p assoc
unset assoc
@@ -158,3 +159,6 @@ ${THIS_SH} ./quotearray3.sub
# behavior of builtins with array subscripts @ and *
${THIS_SH} ./quotearray4.sub
# behavior of unset with quoted and unquoted array arguments
${THIS_SH} ./quotearray5.sub
+17
View File
@@ -91,6 +91,8 @@ echo $?
[[ -v assoc['$key4'] ]]
echo $?
unset -v assoc
declare -A aa
aa[$key5]=foo
@@ -112,3 +114,18 @@ test -v aa[$key6]
echo $?
unset aa key
declare -A assoc
mytest ()
{
assoc["$1"]=123
[[ -v assoc["$1"] ]]
printf '[[ -v assoc[%s] ]]; $?=%s\n' "$1" "$?"
}
mytest 'a'
mytest '"'
declare -p assoc
unset -v assoc
unset -f mytest
+4
View File
@@ -101,3 +101,7 @@ declare -p assoc
shopt -s assoc_expand_once
test -v assoc["$key"] ; echo $?
unset assoc
shopt -u assoc_expand_once
+20
View File
@@ -33,6 +33,7 @@ unset 'assoc[$var]'
declare -p assoc
unset assoc
shopt -u assoc_expand_once
declare -A a
a['$(echo foo)']=1
@@ -95,3 +96,22 @@ declare -p array
BASH_COMPAT=51
unset array[@]
declare -p array
declare -A map; key='foo$(uname >/dev/tty)bar'; map[$key]=1
declare -p map
echo ${map["$key"]}
unset map["$key"]
declare -p map
unset map
declare -A blah
blah['$(DOESNOTEXIST)']=broken
for i in "${!blah[@]}"; do echo "$i"; done
for i in "${!blah[@]}"; do unset blah["$i"]; done
declare -p blah
unset blah
+124
View File
@@ -0,0 +1,124 @@
# 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 <http://www.gnu.org/licenses/>.
#
# a set of tests for unset to try to ensure that subscripts are only expanded
# once. Derived from tests submitted by konsolebox@gmail.com
declare -A a
key='$(echo foo)'
# Here the tokens are valid array references and pass that fact to unset
# post-expansion
# This solves the surprise expansion issues.
a[$key]=1
unset -v a[$key] # this performs normal word splitting
unset -v a["$key"] # prevent word splitting
declare -p a # Displays no element
a['$key']=2
unset -v a['$key']
declare -p a # Displays no element
a["foo"]=3
unset -v a["foo"]
declare -p a # Displays no element
echo -----
# Here the tokens are "strings". They expand and keep the
# original behavior and allows existing scripts to not break.
# It also allows nref or iref references to be transparently
# referenced in it.
# the quotes prevent the arguments from being recognized as valid array
# references before word expansion. since unset doesn't know to treat
# them specially, they're treated as in previous versions and expansion
# is performed as part of evaluating the subscript
a[$key]=1
declare -p a
unset 'a[$key]' # Transforms to a[$key] after expansion
declare -p a # Displays no element
a['$key']=2
unset "a['\$key']" # Transforms to a['$key'] after expansion
declare -p a # Displays no element
a["foo"]=3
unset 'a["foo"]' # Transforms to a["foo"] after expansion
declare -p a # Displays no element
echo -----
# The update also keeps compatibility with already existing behavior of
# unset when assoc_expand_once is enabled, but only for quoted tokens.
a=()
shopt -s assoc_expand_once
a[$key]=1
unset "a[$key]"
declare -p a # Displays no element
a['$key']=2
unset "a[\$key]"
declare -p a # Displays no element
a["foo"]=3
unset "a[foo]"
declare -p a # Displays no element
echo ----------
# For unsetting '@' and all elements:
key=@
declare -A a=(@ v0 . v1)
unset a[$key]
declare -p a # Displays 'declare -A a=([.]="v1" )'
declare -A a=(@ v0 . v1)
unset a[@]
declare -p a # same behavior
echo -----
# these are quoted strings and unset doesn't treat them specially
unset a
shopt -u assoc_expand_once
declare -A a=(@ v0 . v1)
unset 'a[$key]'
declare -p a # Displays 'declare -A a=([.]="v1" )'
declare -A a=(@ v0 . v1)
unset 'a[@]'
declare -p a # same behavior
echo -----
unset a
shopt -s assoc_expand_once
declare -A a=(@ v0 . v1)
unset "a[$key]" # $key is expanded
declare -p a # Displays 'declare -A a=([.]="v1" )'
declare -A a=(@ v0 . v1)
unset 'a[@]'
declare -p a # same behavior