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
				
			
		
							
								
								
									
										6
									
								
								NEWS
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								NEWS
									
										
									
									
									
								
							| 
						 | 
					@ -3,6 +3,12 @@ For full details, see the git log at: https://github.com/ksh93/ksh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Any uppercase BUG_* names are modernish shell bug IDs.
 | 
					Any uppercase BUG_* names are modernish shell bug IDs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2021-04-04:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Harden readonly variables. Readonly variables or arrays no longer allow
 | 
				
			||||||
 | 
					  attribute changes which would otherwise allow their value to be altered.
 | 
				
			||||||
 | 
					  Expanded support for readonly variables within multidimensional arrays.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2021-04-03:
 | 
					2021-04-03:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fixed a bug that caused the uname builtin's -d option to change the output
 | 
					- Fixed a bug that caused the uname builtin's -d option to change the output
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -732,6 +732,11 @@ static int     setall(char **argv,register int flag,Dt_t *troot,struct tdata *tp
 | 
				
			||||||
			np = nv_open(name,troot,nvflags|((nvflags&NV_ASSIGN)?0:NV_ARRAY)|((iarray|(nvflags&(NV_REF|NV_NOADD)==NV_REF))?NV_FARRAY:0));
 | 
								np = nv_open(name,troot,nvflags|((nvflags&NV_ASSIGN)?0:NV_ARRAY)|((iarray|(nvflags&(NV_REF|NV_NOADD)==NV_REF))?NV_FARRAY:0));
 | 
				
			||||||
			if(!np)
 | 
								if(!np)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
								if(np->nvflag&NV_RDONLY && !tp->pflag && (flag & ~NV_NOFREE) != NV_RDONLY)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									errormsg(SH_DICT,ERROR_exit(1),e_readonly,nv_name(np));
 | 
				
			||||||
 | 
									UNREACHABLE();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if(nv_isnull(np) && !nv_isarray(np) && nv_isattr(np,NV_NOFREE))
 | 
								if(nv_isnull(np) && !nv_isarray(np) && nv_isattr(np,NV_NOFREE))
 | 
				
			||||||
				nv_offattr(np,NV_NOFREE);
 | 
									nv_offattr(np,NV_NOFREE);
 | 
				
			||||||
			else if(tp->tp && !nv_isattr(np,NV_MINIMAL|NV_EXPORT) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)) && (ap->nelem&ARRAY_TREE))
 | 
								else if(tp->tp && !nv_isattr(np,NV_MINIMAL|NV_EXPORT) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)) && (ap->nelem&ARRAY_TREE))
 | 
				
			||||||
| 
						 | 
					@ -889,14 +894,7 @@ static int     setall(char **argv,register int flag,Dt_t *troot,struct tdata *tp
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if((flag&NV_RDONLY) && (curflag&NV_RDONLY))
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					errormsg(SH_DICT,ERROR_exit(1),e_readonly,nv_name(np));
 | 
					 | 
				
			||||||
					UNREACHABLE();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				newflag = curflag & ~flag;
 | 
									newflag = curflag & ~flag;
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (tp->aflag && (tp->argnum || (curflag!=newflag)))
 | 
								if (tp->aflag && (tp->argnum || (curflag!=newflag)))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if(shp->subshell)
 | 
									if(shp->subshell)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SH_RELEASE_FORK	"93u+m"		/* only change if you develop a new ksh93 fork */
 | 
					#define SH_RELEASE_FORK	"93u+m"		/* only change if you develop a new ksh93 fork */
 | 
				
			||||||
#define SH_RELEASE_SVER	"1.0.0-alpha"	/* semantic version number: https://semver.org */
 | 
					#define SH_RELEASE_SVER	"1.0.0-alpha"	/* semantic version number: https://semver.org */
 | 
				
			||||||
#define SH_RELEASE_DATE	"2021-04-03"	/* must be in this format for $((.sh.version)) */
 | 
					#define SH_RELEASE_DATE	"2021-04-04"	/* must be in this format for $((.sh.version)) */
 | 
				
			||||||
#define SH_RELEASE_CPYR	"(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
 | 
					#define SH_RELEASE_CPYR	"(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
 | 
					/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1522,6 +1522,15 @@ char *nv_endsubscript(Namval_t *np, register char *cp, int mode)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if(mode && np)
 | 
						if(mode && np)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							/* Block an attempt to alter a readonly array via subscript assignment or by appending the array.
 | 
				
			||||||
 | 
							   However need to allow instances of type variables. This exception is observed when np->nvflag
 | 
				
			||||||
 | 
							   has NV_BINARY and NV_LJUST set besides NV_RDONLY and NV_ARRAY. */
 | 
				
			||||||
 | 
							if(nv_isattr(np,NV_RDONLY) && nv_isattr(np,NV_ARRAY) && mode&NV_ASSIGN && np->nvflag&(NV_BINARY|NV_LJUST)^(NV_BINARY|NV_LJUST))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								errormsg(SH_DICT,ERROR_exit(1),e_readonly,nv_name(np));
 | 
				
			||||||
 | 
								UNREACHABLE();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Namarr_t *ap = nv_arrayptr(np);
 | 
							Namarr_t *ap = nv_arrayptr(np);
 | 
				
			||||||
		int scan = 0;
 | 
							int scan = 0;
 | 
				
			||||||
#if SHOPT_FIXEDARRAY
 | 
					#if SHOPT_FIXEDARRAY
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@
 | 
				
			||||||
#   define SH_DICT	"libshell"
 | 
					#   define SH_DICT	"libshell"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAXLEVEL	9
 | 
					#define MAXLEVEL	1024
 | 
				
			||||||
#define SMALL_STACK	12
 | 
					#define SMALL_STACK	12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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