mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-17 21:18:06 +02:00
53546,53557 (plus test): Fix scoping of "placeholder" named references
When using placeholders declared several levels earlier than assignment: 1) Searching "up" for "typeset -n -u" could find deeper locals than intended 2) Searching for a subscript reference could skip to the top level 3) Exiting a function scope could incorrectly change the reference level
This commit is contained in:
parent
d89f3a1d08
commit
f555e902db
3 changed files with 191 additions and 6 deletions
|
@ -1,3 +1,12 @@
|
|||
2025-05-05 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 53557 (plus test): Src/params.c, Test/K01nameref.ztst:
|
||||
Fix one more scoping issue with "typeset -u -n" references
|
||||
|
||||
* 53546 (plus test): Src/params.c, Test/K01nameref.ztst:
|
||||
Fix several errors when using "placeholder" named references
|
||||
declared at scopes surrounding the scope where they are assigned.
|
||||
|
||||
2025-05-04 dana@dana.is <dana@dana.is>
|
||||
|
||||
* Max Coplan: 53535: Util/helpfiles: fix builds with
|
||||
|
|
28
Src/params.c
28
Src/params.c
|
@ -2231,7 +2231,13 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
|
|||
*ss = 0;
|
||||
}
|
||||
Param p1 = (Param)gethashnode2(paramtab, ref);
|
||||
if (!(p1 && (pm = upscope(p1, pm->base))) ||
|
||||
if (p1) {
|
||||
int scope = ((pm->node.flags & PM_NAMEREF) ?
|
||||
((pm->node.flags & PM_UPPER) ? -(pm->base) :
|
||||
pm->base) : locallevel);
|
||||
pm = upscope(p1, scope);
|
||||
}
|
||||
if (!(p1 && pm) ||
|
||||
((pm->node.flags & PM_UNSET) &&
|
||||
!(pm->node.flags & PM_DECLARED)))
|
||||
return NULL;
|
||||
|
@ -5885,7 +5891,8 @@ scanendscope(HashNode hn, UNUSED(int flags))
|
|||
export_param(pm);
|
||||
} else
|
||||
unsetparam_pm(pm, 0, 0);
|
||||
} else if ((pm->node.flags & PM_NAMEREF) && pm->base > pm->level)
|
||||
} else if ((pm->node.flags & PM_NAMEREF) &&
|
||||
pm->base > pm->level && pm->base > locallevel)
|
||||
pm->base = locallevel;
|
||||
}
|
||||
|
||||
|
@ -6291,7 +6298,7 @@ resolve_nameref(Param pm, const Asgment stop)
|
|||
if (pm) {
|
||||
if (!(stop && (stop->flags & (PM_LOCAL)))) {
|
||||
int scope = ((pm->node.flags & PM_NAMEREF) ?
|
||||
((pm->node.flags & PM_UPPER) ? -1 :
|
||||
((pm->node.flags & PM_UPPER) ? -(pm->base) :
|
||||
pm->base) : ((Param)hn)->level);
|
||||
hn = (HashNode)upscope((Param)hn, scope);
|
||||
}
|
||||
|
@ -6365,6 +6372,7 @@ setscope(Param pm)
|
|||
if (t) {
|
||||
pm->width = t - refname;
|
||||
*t = '[';
|
||||
refname = dupstrpfx(refname, pm->width);
|
||||
}
|
||||
if (basepm) {
|
||||
if (basepm->node.flags & PM_NAMEREF) {
|
||||
|
@ -6393,11 +6401,19 @@ setscope(Param pm)
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else if (!pm->base) {
|
||||
pm->base = basepm->level;
|
||||
if ((pm->node.flags & PM_UPPER) &&
|
||||
(basepm = upscope(basepm, -(locallevel-1))))
|
||||
pm->base = basepm->level;
|
||||
}
|
||||
} else if (pm->base < locallevel && refname &&
|
||||
(basepm = (Param)getparamnode(realparamtab, refname)))
|
||||
(basepm = (Param)getparamnode(realparamtab, refname))) {
|
||||
pm->base = basepm->level;
|
||||
if ((pm->node.flags & PM_UPPER) &&
|
||||
(basepm = upscope(basepm, -(locallevel-1))))
|
||||
pm->base = basepm->level;
|
||||
}
|
||||
if (pm->base > pm->level) {
|
||||
if (EMULATION(EMULATE_KSH)) {
|
||||
zerr("%s: global reference cannot refer to local variable",
|
||||
|
@ -6422,7 +6438,7 @@ upscope(Param pm, int reflevel)
|
|||
{
|
||||
Param up = pm->old;
|
||||
while (up && up->level >= reflevel) {
|
||||
if (reflevel < 0 && up->level < locallevel)
|
||||
if (reflevel < 0 && up->level < -(reflevel))
|
||||
break;
|
||||
pm = up;
|
||||
up = up->old;
|
||||
|
|
|
@ -7,6 +7,76 @@
|
|||
|
||||
: ${ZTST_continue::=1}
|
||||
|
||||
# The following test allows to assess what different types of named
|
||||
# references refer to during their lifetime depending on where they
|
||||
# were initialized and whether they were defined with or without the
|
||||
# "-u" flag.
|
||||
#
|
||||
# The first parameter determines whether the named references are
|
||||
# defined with or without the flag "-u".
|
||||
#
|
||||
# The second parameter determines where the named references are
|
||||
# initialized. In all cases the named references are defined at the
|
||||
# start of function "g". With value "0" they are initialized at the
|
||||
# same place (in the same statement). With the other values, the
|
||||
# initialization is delayed until later, the greater the value and the
|
||||
# later the initialization.
|
||||
|
||||
function e() {
|
||||
local s=$0 a=($0);
|
||||
f "$@";
|
||||
}
|
||||
|
||||
function f() {
|
||||
local s=$0 a=($0);
|
||||
g "$@";
|
||||
}
|
||||
|
||||
function g() {
|
||||
if (($2)); then local -n $1 rs ra rs1 ra1;
|
||||
else local -n $1 rs=s ra=a rs1="s[1]" ra1="a[1]"; fi;
|
||||
if (($2 == 1)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
|
||||
echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
local s=$0 a=($0);
|
||||
if (($2 == 2)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
|
||||
echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
h "$@";
|
||||
echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
}
|
||||
|
||||
function h() {
|
||||
if (($2 == 3)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
|
||||
echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
local s=$0 a=($0);
|
||||
if (($2 == 4)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
|
||||
echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
i "$@";
|
||||
echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
# Check that re-entering the same scope doesn't undo scope exit
|
||||
k "$@"
|
||||
}
|
||||
|
||||
function i() {
|
||||
if (($2 == 5)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
|
||||
echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
local s=$0 a=($0);
|
||||
if (($2 == 6)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
|
||||
echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
j "$@";
|
||||
echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
k "$@";
|
||||
}
|
||||
|
||||
function j() {
|
||||
echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
local s=$0 a=($0);
|
||||
echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
|
||||
}
|
||||
|
||||
functions -c j k
|
||||
|
||||
local s=T a=(T);
|
||||
|
||||
%test
|
||||
|
||||
typeset -n ptr
|
||||
|
@ -902,6 +972,96 @@ F:previously this could create an infinite recursion and crash
|
|||
1:create nameref by pattern match not allowed
|
||||
*?*typeset:1: -m not allowed with -n
|
||||
|
||||
e -u 0
|
||||
0:assignment at different scope than declaration, -u 0
|
||||
>g:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>g:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>j:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>j:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>g:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
|
||||
e '' 0
|
||||
0:assignment at different scope than declaration, '' 0
|
||||
>g:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>g:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>j:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>j:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>g:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
|
||||
e -u 2
|
||||
0:assignment at different scope than declaration, -u 2
|
||||
>g:1: rs= - ra= - rs1= - ra1=
|
||||
>g:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>j:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>j:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>i:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>h:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:1: rs=f - ra=f - rs1=f - ra1=f
|
||||
>k:2: rs=f - ra=f - rs1=f - ra1=f
|
||||
>g:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
|
||||
e -u 6
|
||||
0:assignment at different scope than declaration, -u 6
|
||||
>g:1: rs= - ra= - rs1= - ra1=
|
||||
>g:2: rs= - ra= - rs1= - ra1=
|
||||
>h:1: rs= - ra= - rs1= - ra1=
|
||||
>h:2: rs= - ra= - rs1= - ra1=
|
||||
>i:1: rs= - ra= - rs1= - ra1=
|
||||
>i:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>j:1: rs=h - ra=h - rs1=h - ra1=h
|
||||
>j:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>i:3: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:1: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>h:3: rs=g - ra=g - rs1=g - ra1=g
|
||||
>k:1: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>g:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
|
||||
e '' 6
|
||||
0:assignment at different scope than declaration, '' 6
|
||||
>g:1: rs= - ra= - rs1= - ra1=
|
||||
>g:2: rs= - ra= - rs1= - ra1=
|
||||
>h:1: rs= - ra= - rs1= - ra1=
|
||||
>h:2: rs= - ra= - rs1= - ra1=
|
||||
>i:1: rs= - ra= - rs1= - ra1=
|
||||
>i:2: rs=i - ra=i - rs1=i - ra1=i
|
||||
>j:1: rs=i - ra=i - rs1=i - ra1=i
|
||||
>j:2: rs=i - ra=i - rs1=i - ra1=i
|
||||
>i:3: rs=i - ra=i - rs1=i - ra1=i
|
||||
>k:1: rs=i - ra=i - rs1=i - ra1=i
|
||||
>k:2: rs=i - ra=i - rs1=i - ra1=i
|
||||
>h:3: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:1: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>g:3: rs=g - ra=g - rs1=g - ra1=g
|
||||
|
||||
#
|
||||
# The following tests are run in interactive mode, using PS1 as an
|
||||
# assignable special with side-effects. This crashed at one time.
|
||||
|
|
Loading…
Reference in a new issue