mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Hardening of readonly variables (#239)
Ksh currently restricts readonly scalar variables from having their values directly changed via a value assignment. However, since ksh allows variable attributes to be altered, the variable's value can be indirectly altered. For instance, if TMOUT=900 (for a 15 minute idle timeout) was set to readonly, all that is needed to alter the value of TMOUT from 900 to 0 is to issue 'typeset -R1 TMOUT', perhaps followed by a 'typeset -i TMOUT' to turn off the shell's timeout value. In addition, there are problems with arrays. The following is incorrectly allowed: typeset -a arr=((a b c) 1) readonly arr arr[0][1]=d arr=(alphas=(a b c);name=x) readonly arr.alphas arr.alphas[1]=([b]=5) arr=(alphas=(a b c);name=x) readonly arr.alphas arr.alphas[1]=(b) typeset -C arr=(typeset -r -a alphas=(a b c);name=x) arr.alphas[1]=() src/cmd/ksh93/bltins/typeset.c: setall(): - Relocate readonly attribute check higher up the code and widen its application to issue an error message if the pre-existing name-pair has the readonly bit flag set. - To avoid compatibility problems, don't check for readonly if NV_RDONLY is the only attribute set (ignoring NV_NOFREE). This allows 'readonly foo; readonly foo' to keep working. src/cmd/ksh93/sh/array.c: nv_endsubscript(): - Apply a readonly flag check when an array subscript or append assignment occurs, but allow type variables (typeset -T) as they utilize '-r' for 'required' sub-variables. src/cmd/ksh93/tests/readonly.sh: - New file. Create readonly tests that validate the warning message and validate that the readonly variable did not change. src/cmd/ksh93/sh/streval.c: - Bump MAXLEVEL from 9 to 1024 as a workaround for arithmetic expansion, avoiding a spurious error about too much recursion when the readonly.sh tests are run. This change is backported from ksh 93v-. TODO: debug a spurious increase in arithmetic recursion level variable when readonly.sh tests with 'typeset -i' are run. That is a different bug for a different commit. Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
parent
c4f980eb29
commit
264ba48bdd
6 changed files with 357 additions and 9 deletions
335
src/cmd/ksh93/tests/readonly.sh
Normal file
335
src/cmd/ksh93/tests/readonly.sh
Normal file
|
@ -0,0 +1,335 @@
|
|||
########################################################################
|
||||
# #
|
||||
# This file is part of the ksh 93u+m package #
|
||||
# Copyright (c) 1982-2012 AT&T Intellectual Property #
|
||||
# Copyright (c) 2021 Contributors to ksh 93u+m #
|
||||
# <https://github.com/ksh93/ksh> #
|
||||
# and is licensed under the #
|
||||
# Eclipse Public License, Version 1.0 #
|
||||
# #
|
||||
# A copy of the License is available at #
|
||||
# http://www.eclipse.org/org/documents/epl-v10.html #
|
||||
# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
|
||||
# #
|
||||
# hyenias #
|
||||
# #
|
||||
########################################################################
|
||||
|
||||
. "${SHTESTS_COMMON:-${0%/*}/_common}"
|
||||
|
||||
rtests=(
|
||||
(
|
||||
ini='typeset -ri x=900'
|
||||
chg='typeset -R1 x'
|
||||
res='typeset -p x'
|
||||
exp='typeset -r -i x=900'
|
||||
)
|
||||
(
|
||||
ini='typeset -ri x=900'
|
||||
chg='typeset -X x; typeset -L1 x; typeset -i x'
|
||||
res='typeset -p x'
|
||||
exp='typeset -r -i x=900'
|
||||
)
|
||||
(
|
||||
ini='typeset -L3 x=0123; readonly x'
|
||||
chg='typeset -Z5 x'
|
||||
res='typeset -p x'
|
||||
exp='typeset -r -L 3 x=012'
|
||||
)
|
||||
(
|
||||
ini='typeset -rL3 x=0123'
|
||||
chg='typeset -R5 x'
|
||||
res='typeset -p x'
|
||||
exp='typeset -r -L 3 x=012'
|
||||
)
|
||||
(
|
||||
ini='typeset -rL3 x=0123'
|
||||
chg='typeset -L5 x'
|
||||
res='typeset -p x'
|
||||
exp='typeset -r -L 3 x=012'
|
||||
)
|
||||
(
|
||||
ini='typeset -R3 x; typeset -r x'
|
||||
chg='x=0'
|
||||
res='typeset -p x'
|
||||
exp='typeset -r -R 3 x'
|
||||
)
|
||||
(
|
||||
ini='set -A arr[0] a b c; readonly arr'
|
||||
chg='arr[1]=1'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) )'
|
||||
)
|
||||
(
|
||||
ini='set -A arr[0] a b c; readonly arr'
|
||||
chg='arr[0][1]=d'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) )'
|
||||
)
|
||||
(
|
||||
ini='set -A arr[0] a b c; readonly arr'
|
||||
chg='set +A arr 1'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) )'
|
||||
)
|
||||
(
|
||||
ini='typeset -a arr=((a b c) 1); readonly arr'
|
||||
chg='arr[1]=d'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra arr=((a b c) 1)'
|
||||
chg='arr[1]=d'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra arr=((a b c) 1)'
|
||||
chg='arr[1]=()'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -a arr=((a b c) 1)'
|
||||
chg='arr[0][1]=d'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -a arr=((a b c) 1)'
|
||||
chg='arr[0][1]=()'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -a arr=((a b c) 1)'
|
||||
chg='arr[0][1]=(d)'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(# For a move, the unset should be blocked but copy succeeds.
|
||||
ini='readonly old=RDONLY'
|
||||
chg='typeset -m new=old'
|
||||
res='typeset -p old new'
|
||||
exp=$'typeset -r old=RDONLY\nnew=RDONLY'
|
||||
)
|
||||
(
|
||||
ini='typeset -C arr=(typeset -r -a alphas=(a b c);name=x)'
|
||||
chg='arr.name=y; arr.alphas[1]=b'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -C arr=(typeset -r -a alphas=(a b c);name=y)'
|
||||
)
|
||||
(
|
||||
ini='typeset -C arr=(typeset -r -a alphas=(a b c);name=x)'
|
||||
chg='arr.name=y; arr.alphas[1]=()'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -C arr=(typeset -r -a alphas=(a b c);name=y)'
|
||||
)
|
||||
(
|
||||
ini='typeset -C arr=(typeset -r -a alphas=(a b c);name=x)'
|
||||
chg='arr.name=y; arr.alphas[1]=(b)'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -C arr=(typeset -r -a alphas=(a b c);name=y)'
|
||||
)
|
||||
(
|
||||
ini='arr=(alphas=(a b c);name=x); readonly arr.alphas'
|
||||
chg='arr.alphas[1]=([b]=5)'
|
||||
res='typeset -p arr arr.alphas'
|
||||
exp=$'typeset -C arr=(typeset -r -a alphas=(a b c);name=x)\ntypeset -r -a arr.alphas=(a b c)'
|
||||
)
|
||||
(
|
||||
ini='arr=(alphas=(a b c);name=x); readonly arr.alphas'
|
||||
chg='arr.alphas[1]=(b)'
|
||||
res='typeset -p arr arr.alphas'
|
||||
exp=$'typeset -C arr=(typeset -r -a alphas=(a b c);name=x)\ntypeset -r -a arr.alphas=(a b c)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -E arr=(0 1 2 3)'
|
||||
chg='arr[1]=()'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -E arr=(0 1 2 3)'
|
||||
)
|
||||
(
|
||||
ini='typeset -T FB_t=(typeset x=foo y=bar; typeset -r z=${_.y}; create() { _.y=bam; }; )'
|
||||
chg='FB_t fb; fb.z=foo'
|
||||
res='typeset -p fb'
|
||||
exp='FB_t fb=(x=foo;y=bam;typeset -r z=bar)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra arr=((a b c) 1)'
|
||||
chg='arr+=(2)'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra arr=((a b c) 1)'
|
||||
chg='arr[0]+=(d)'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a arr=((a b c) 1)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[1] += 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[1] -= 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[1] *= 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[1] /= 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[0][1] += 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[0][1] -= 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[0][1] *= 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -ra -i arr=((10 11 12) 3 4)'
|
||||
chg='(( arr[0][1] /= 2 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -a -i arr=((10 11 12) 3 4)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=10 [b]=20 [c]=30)'
|
||||
chg='arr[b]=40'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=10 [b]=20 [c]=30)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=10 [b]=20 [c]=30)'
|
||||
chg='arr[b]=()'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=10 [b]=20 [c]=30)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=10 [b]=20 [c]=30)'
|
||||
chg='arr[b]=(40)'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=10 [b]=20 [c]=30)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
chg='arr[c]=30'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
chg='arr[c]+=30'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
chg='arr[a][11]=0xb'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
chg='arr[a][11]+=0xb'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
chg='arr[a][13]=XIII'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A arr=([a]=([10]=X [11]=XI [12]=XII) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
chg='(( arr[b] += 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
chg='(( arr[b] -= 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
chg='(( arr[b] *= 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
chg='(( arr[b] /= 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=10 [b]=20 [c]=30)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
chg='(( arr[a][XI] += 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
chg='(( arr[a][XI] -= 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
chg='(( arr[a][XI] *= 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
)
|
||||
(
|
||||
ini='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
chg='(( arr[a][XI] /= 5 ))'
|
||||
res='typeset -p arr'
|
||||
exp='typeset -r -A -i arr=([a]=([X]=10 [XI]=11 [XII]=12) [b]=20)'
|
||||
)
|
||||
)
|
||||
|
||||
typeset -i i
|
||||
n=${#rtests[@]}
|
||||
for ((i=0; i<$n; i++))
|
||||
do
|
||||
got=$(
|
||||
trap "${rtests[$i].res}" EXIT
|
||||
eval "${rtests[$i].ini}"
|
||||
eval "${rtests[$i].chg}" 2>&1
|
||||
)
|
||||
[[ $got == *$': is read only\n'* ]] || err_exit "Readonly variable did not warn for rtests[$i]: "\
|
||||
"setup='${rtests[$i].ini}', change='${rtests[$i].chg}'"
|
||||
got=${got#*$': is read only\n'}
|
||||
[[ ${rtests[$i].exp} == "$got" ]] || err_exit "Readonly variable changed on rtests[$i]: "\
|
||||
"expected '${rtests[$i].exp}', got '$got'"
|
||||
done
|
||||
unset i n got rtests
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
Loading…
Add table
Add a link
Reference in a new issue