Skip to content

Commit e1fed54

Browse files
paltherrbartschaefer
authored andcommitted
53782: Src/params.c, Test/K01nameref.ztst: changes to nameref base level:
- avoid changing base on assignment; - omit base level for up-scope references - do not follow reference chains for base level of new references
1 parent 1e0d2b0 commit e1fed54

File tree

3 files changed

+103
-51
lines changed

3 files changed

+103
-51
lines changed

ChangeLog

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
2025-10-26 Bart Schaefer <[email protected]>
22

3-
* Philippe: 53732: avoid tail-call exec in always block
3+
* Philippe: 53732: Src/loop.c, Test/A01grammar.ztst: avoid tail-call
4+
exec in always block
45

5-
* Philippe: 53781: fix loading of autoload variable via a reference
6+
* Philippe: 53781: Src/params.c, Test/B02typeset.ztst,
7+
Test/K01nameref.ztst: fix load of autoload variable via a reference
8+
9+
* Philippe: 53782: Src/params.c, Test/K01nameref.ztst: changes to
10+
handling of nameref base level: avoid changing base on assignment;
11+
omit base level for up-scope references; do not follow reference
12+
chains when computing base level of new references
613

714
2025-10-24 Oliver Kiddle <[email protected]>
815

Src/params.c

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,10 +2239,10 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
22392239
}
22402240
Param p1 = (Param)gethashnode2(paramtab, ref);
22412241
if (p1) {
2242-
int scope = ((pm->node.flags & PM_NAMEREF) ?
2243-
((pm->node.flags & PM_UPPER) ? -(pm->base) :
2244-
pm->base) : locallevel);
2245-
pm = upscope(p1, scope);
2242+
if (pm->node.flags & PM_UPPER)
2243+
pm = upscope_upper(p1, pm->level - 1);
2244+
else
2245+
pm = upscope(p1, pm->base);
22462246
pm = (Param)loadparamnode(paramtab, pm, ref);
22472247
}
22482248
if (!(p1 && pm) ||
@@ -3324,7 +3324,11 @@ assignsparam(char *s, char *val, int flags)
33243324
}
33253325
}
33263326

3327+
if (v->pm->node.flags & PM_NAMEREF)
3328+
v->pm->node.flags |= PM_NEWREF;
33273329
assignstrvalue(v, val, flags);
3330+
if (v->pm->node.flags & PM_NAMEREF)
3331+
v->pm->node.flags &= ~PM_NEWREF;
33283332
unqueue_signals();
33293333
return v->pm;
33303334
}
@@ -6314,12 +6318,13 @@ resolve_nameref(Param pm, const Asgment stop)
63146318
} else if ((hn = gethashnode2(realparamtab, seek))) {
63156319
if (pm) {
63166320
if (!(stop && (stop->flags & (PM_LOCAL)))) {
6317-
int scope = ((pm->node.flags & PM_NAMEREF) ?
6318-
((pm->node.flags & PM_UPPER) ?
6319-
/* pm->base == 0 means not set yet */
6320-
-(pm->base ? pm->base : pm->level) :
6321-
pm->base) : ((Param)hn)->level);
6322-
hn = (HashNode)upscope((Param)hn, scope);
6321+
if ((pm->node.flags & PM_NAMEREF) &&
6322+
(pm->node.flags & PM_UPPER))
6323+
hn = (HashNode)upscope_upper((Param)hn, pm->level - 1);
6324+
else
6325+
hn = (HashNode)upscope((Param)hn,
6326+
(pm->node.flags & PM_NAMEREF) ?
6327+
(pm->base) : ((Param)hn)->level);
63236328
}
63246329
hn = loadparamnode(paramtab, (Param)hn, seek);
63256330
/* user can't tag a nameref, safe for loop detection */
@@ -6374,24 +6379,44 @@ setscope(Param pm)
63746379
char *t = refname ? itype_end(refname, INAMESPC, 0) : NULL;
63756380
int q = queue_signal_level();
63766381

6382+
/* Compute pm->width */
63776383
/* Temporarily change nameref to array parameter itself */
63786384
if (t && *t == '[')
63796385
*t = 0;
63806386
else
63816387
t = 0;
6382-
stop.name = "";
6388+
if (t) {
6389+
pm->width = t - refname;
6390+
*t = '[';
6391+
refname = dupstrpfx(refname, pm->width);
6392+
}
6393+
6394+
/* Compute pm->base */
6395+
if (!(pm->node.flags & PM_UPPER) && refname &&
6396+
(basepm = (Param)gethashnode2(realparamtab, refname)) &&
6397+
(basepm = (Param)loadparamnode(realparamtab, basepm, refname)) &&
6398+
(!(basepm->node.flags & PM_NEWREF) || (basepm = basepm->old))) {
6399+
pm->base = basepm->level;
6400+
}
6401+
if (pm->base > pm->level) {
6402+
if (EMULATION(EMULATE_KSH)) {
6403+
zerr("%s: global reference cannot refer to local variable",
6404+
pm->node.nam);
6405+
unsetparam_pm(pm, 0, 1);
6406+
} else if (isset(WARNNESTEDVAR))
6407+
zwarn("reference %s in enclosing scope set to local variable %s",
6408+
pm->node.nam, refname);
6409+
}
6410+
6411+
/* Check for self references */
6412+
stop.name = pm->node.nam;
63836413
stop.value.scalar = NULL;
63846414
stop.flags = PM_NAMEREF;
63856415
if (locallevel && !(pm->node.flags & PM_UPPER))
63866416
stop.flags |= PM_LOCAL;
63876417
dont_queue_signals(); /* Prevent unkillable loops */
63886418
basepm = (Param)resolve_nameref(pm, &stop);
63896419
restore_queue_signals(q);
6390-
if (t) {
6391-
pm->width = t - refname;
6392-
*t = '[';
6393-
refname = dupstrpfx(refname, pm->width);
6394-
}
63956420
if (basepm) {
63966421
if (basepm->node.flags & PM_NAMEREF) {
63976422
if (pm == basepm) {
@@ -6419,27 +6444,7 @@ setscope(Param pm)
64196444
break;
64206445
}
64216446
}
6422-
} else if (!pm->base) {
6423-
pm->base = basepm->level;
6424-
if ((pm->node.flags & PM_UPPER) &&
6425-
(basepm = upscope(basepm, -(pm->level))))
6426-
pm->base = basepm->level;
64276447
}
6428-
} else if (pm->base < locallevel && refname &&
6429-
(basepm = (Param)getparamnode(realparamtab, refname))) {
6430-
pm->base = basepm->level;
6431-
if ((pm->node.flags & PM_UPPER) &&
6432-
(basepm = upscope(basepm, -(pm->level))))
6433-
pm->base = basepm->level;
6434-
}
6435-
if (pm->base > pm->level) {
6436-
if (EMULATION(EMULATE_KSH)) {
6437-
zerr("%s: global reference cannot refer to local variable",
6438-
pm->node.nam);
6439-
unsetparam_pm(pm, 0, 1);
6440-
} else if (isset(WARNNESTEDVAR))
6441-
zwarn("reference %s in enclosing scope set to local variable %s",
6442-
pm->node.nam, refname);
64436448
}
64446449
if (refname && upscope(pm, pm->base) == pm &&
64456450
strcmp(pm->node.nam, refname) == 0) {
@@ -6456,13 +6461,18 @@ upscope(Param pm, int reflevel)
64566461
{
64576462
Param up = pm->old;
64586463
while (up && up->level >= reflevel) {
6459-
if (reflevel < 0 && up->level < -(reflevel))
6460-
break;
64616464
pm = up;
64626465
up = up->old;
64636466
}
6464-
if (reflevel < 0 && locallevel > 0)
6465-
return pm->level == locallevel ? up : pm;
6467+
return pm;
6468+
}
6469+
6470+
/**/
6471+
mod_export Param
6472+
upscope_upper(Param pm, int reflevel)
6473+
{
6474+
while (pm && pm->level > reflevel)
6475+
pm = pm->old;
64666476
return pm;
64676477
}
64686478

Test/K01nameref.ztst

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,15 +1100,15 @@ F:previously this could create an infinite recursion and crash
11001100
>h:1: rs= - ra= - rs1= - ra1=
11011101
>h:2: rs= - ra= - rs1= - ra1=
11021102
>i:1: rs= - ra= - rs1= - ra1=
1103-
>i:2: rs=g - ra=g - rs1=g - ra1=g
1104-
>j:1: rs=g - ra=g - rs1=g - ra1=g
1105-
>j:2: rs=g - ra=g - rs1=g - ra1=g
1106-
>i:3: rs=g - ra=g - rs1=g - ra1=g
1107-
>k:1: rs=g - ra=g - rs1=g - ra1=g
1108-
>k:2: rs=g - ra=g - rs1=g - ra1=g
1109-
>h:3: rs=g - ra=g - rs1=g - ra1=g
1110-
>k:1: rs=g - ra=g - rs1=g - ra1=g
1111-
>k:2: rs=g - ra=g - rs1=g - ra1=g
1103+
>i:2: rs=f - ra=f - rs1=f - ra1=f
1104+
>j:1: rs=f - ra=f - rs1=f - ra1=f
1105+
>j:2: rs=f - ra=f - rs1=f - ra1=f
1106+
>i:3: rs=f - ra=f - rs1=f - ra1=f
1107+
>k:1: rs=f - ra=f - rs1=f - ra1=f
1108+
>k:2: rs=f - ra=f - rs1=f - ra1=f
1109+
>h:3: rs=f - ra=f - rs1=f - ra1=f
1110+
>k:1: rs=f - ra=f - rs1=f - ra1=f
1111+
>k:2: rs=f - ra=f - rs1=f - ra1=f
11121112
>g:3: rs=f - ra=f - rs1=f - ra1=f
11131113

11141114
e '' 6
@@ -1237,4 +1237,39 @@ F:previously this could create an infinite recursion and crash
12371237
?(eval):zsh/random:6: error when adding parameter `SRANDOM'
12381238
?(eval):6: autoloading module zsh/random failed to define parameter: SRANDOM
12391239

1240+
() {
1241+
typeset var1=var1
1242+
typeset var2=var2
1243+
typeset -n ref1=var1
1244+
echo "ref1=$ref1";
1245+
() {
1246+
typeset -n ref1=var2
1247+
typeset -n ref2=ref1
1248+
echo "ref1=$ref1";
1249+
echo "ref2=$ref2";
1250+
}
1251+
}
1252+
0:regression: don't follow references when computing base scope - part 1
1253+
>ref1=var1
1254+
>ref1=var2
1255+
>ref2=var2
1256+
1257+
() {
1258+
typeset var1=var1
1259+
typeset -n ref1=var1
1260+
echo ref1=$ref1;
1261+
() {
1262+
typeset var2=var2
1263+
typeset -n ref1
1264+
typeset -n ref2=ref1
1265+
ref1=var2
1266+
echo ref1=$ref1;
1267+
echo ref2=$ref2;
1268+
}
1269+
}
1270+
0:regression: don't follow references when computing base scope - part 2
1271+
>ref1=var1
1272+
>ref1=var2
1273+
>ref2=var2
1274+
12401275
%clean

0 commit comments

Comments
 (0)