Skip to content

Commit 1e0d2b0

Browse files
paltherrbartschaefer
authored andcommitted
53781: fix loading of autoload variable via a reference
1 parent 477c689 commit 1e0d2b0

File tree

4 files changed

+135
-11
lines changed

4 files changed

+135
-11
lines changed

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
* Philippe: 53732: avoid tail-call exec in always block
44

5+
* Philippe: 53781: fix loading of autoload variable via a reference
6+
57
2025-10-24 Oliver Kiddle <[email protected]>
68

79
* 54002: Src/parse.c: silence compiler warning for static function

Src/params.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -525,18 +525,18 @@ newparamtable(int size, char const *name)
525525

526526
/**/
527527
static HashNode
528-
getparamnode(HashTable ht, const char *nam)
528+
loadparamnode(HashTable ht, Param pm, const char *nam)
529529
{
530-
HashNode hn = gethashnode2(ht, nam);
531-
Param pm = (Param) hn;
532-
533530
if (pm && (pm->node.flags & PM_AUTOLOAD) && pm->u.str) {
531+
int level = pm->level;
534532
char *mn = dupstring(pm->u.str);
535-
536-
(void)ensurefeature(mn, "p:", (pm->node.flags & PM_AUTOALL) ? NULL :
537-
nam);
538-
hn = gethashnode2(ht, nam);
539-
if (!hn) {
533+
(void)ensurefeature(mn, "p:", nam);
534+
pm = (Param)gethashnode2(ht, nam);
535+
while (pm && pm->level > level)
536+
pm = pm->old;
537+
if (pm && (pm->level != level || (pm->node.flags & PM_AUTOLOAD)))
538+
pm = NULL;
539+
if (!pm) {
540540
/*
541541
* This used to be a warning, but surely if we allow
542542
* stuff to go ahead with the autoload stub with
@@ -546,7 +546,14 @@ getparamnode(HashTable ht, const char *nam)
546546
nam);
547547
}
548548
}
549+
return (HashNode)pm;
550+
}
549551

552+
/**/
553+
static HashNode
554+
getparamnode(HashTable ht, const char *nam)
555+
{
556+
HashNode hn = loadparamnode(ht, (Param)gethashnode2(ht, nam), nam);
550557
if (hn && ht == realparamtab && !(hn->flags & PM_UNSET))
551558
hn = resolve_nameref((Param)hn, NULL);
552559
return hn;
@@ -2236,6 +2243,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
22362243
((pm->node.flags & PM_UPPER) ? -(pm->base) :
22372244
pm->base) : locallevel);
22382245
pm = upscope(p1, scope);
2246+
pm = (Param)loadparamnode(paramtab, pm, ref);
22392247
}
22402248
if (!(p1 && pm) ||
22412249
((pm->node.flags & PM_UNSET) &&
@@ -6313,12 +6321,11 @@ resolve_nameref(Param pm, const Asgment stop)
63136321
pm->base) : ((Param)hn)->level);
63146322
hn = (HashNode)upscope((Param)hn, scope);
63156323
}
6324+
hn = loadparamnode(paramtab, (Param)hn, seek);
63166325
/* user can't tag a nameref, safe for loop detection */
63176326
pm->node.flags |= PM_TAGGED;
63186327
}
63196328
if (hn) {
6320-
if (hn->flags & PM_AUTOLOAD)
6321-
hn = getparamnode(realparamtab, seek);
63226329
if (!(hn->flags & PM_UNSET))
63236330
hn = resolve_nameref((Param)hn, stop);
63246331
}

Test/B02typeset.ztst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,3 +1120,60 @@
11201120
1:Regression test for {...} parsing in typeset
11211121
?(eval):typeset:2: not valid in this context: {X}
11221122
?(eval):typeset:3: not valid in this context: {X}
1123+
1124+
zmodload -u zsh/random
1125+
echo v=${SRANDOM/<->/integer}
1126+
typeset SRANDOM
1127+
echo v=${SRANDOM/<->/integer}
1128+
0:Global non -h variable doesn't hide special variable
1129+
>v=integer
1130+
>v=integer
1131+
1132+
zmodload -u zsh/random
1133+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1134+
typeset -g SRANDOM
1135+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1136+
echo v=${SRANDOM/<->/integer}
1137+
0:Global non -h variable doesn't hide autoload variable
1138+
>z=SRANDOM (zsh/random)
1139+
>z=SRANDOM (zsh/random)
1140+
>v=integer
1141+
1142+
zmodload -u zsh/random
1143+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1144+
typeset -gh SRANDOM
1145+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1146+
echo v=${SRANDOM/<->/integer}
1147+
0:Global -h variable doesn't hide autoload variable
1148+
>z=SRANDOM (zsh/random)
1149+
>z=SRANDOM (zsh/random)
1150+
>v=integer
1151+
1152+
zmodload -u zsh/random
1153+
echo v=${SRANDOM/<->/integer}
1154+
typeset SRANDOM
1155+
echo v=${SRANDOM/<->/integer}
1156+
0:Local non -h variable doesn't hide special variable
1157+
>v=integer
1158+
>v=integer
1159+
1160+
zmodload -u zsh/random
1161+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1162+
typeset SRANDOM
1163+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1164+
echo v=${SRANDOM/<->/integer}
1165+
0:Local non -h variable hides autoload variable
1166+
F:This is a bug, the non -h variable should not hide the autoload variable
1167+
>z=SRANDOM (zsh/random)
1168+
>z=
1169+
>v=
1170+
1171+
zmodload -u zsh/random
1172+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1173+
typeset -h SRANDOM
1174+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1175+
echo v=${SRANDOM/<->/integer}
1176+
0:Local -h variable hides autoload variable
1177+
>z=SRANDOM (zsh/random)
1178+
>z=
1179+
>v=

Test/K01nameref.ztst

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,4 +1179,62 @@ F:previously this could create an infinite recursion and crash
11791179
>typeset PS1=zz
11801180
*?*
11811181

1182+
zmodload -u zsh/random
1183+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1184+
typeset -n ref=SRANDOM
1185+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1186+
echo v=${ref/<->/integer}
1187+
zmodload -u zsh/random
1188+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1189+
echo v=${ref/<->/integer}
1190+
0:Referring and dereferring an autoload variable loads it (direct)
1191+
>z=SRANDOM (zsh/random)
1192+
>z=
1193+
>v=integer
1194+
>z=SRANDOM (zsh/random)
1195+
>v=integer
1196+
1197+
zmodload -u zsh/random
1198+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1199+
typeset -n ref=SRANDOM[1,20]
1200+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1201+
echo v=${ref/<->/integer}
1202+
zmodload -u zsh/random
1203+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1204+
echo v=${ref/<->/integer}
1205+
0:Referring and dereferring an autoload variable loads it (subscript)
1206+
>z=SRANDOM (zsh/random)
1207+
>z=
1208+
>v=integer
1209+
>z=SRANDOM (zsh/random)
1210+
>v=integer
1211+
1212+
typeset -n ref=SRANDOM
1213+
echo v=${ref/<->/integer}
1214+
zmodload -u zsh/random
1215+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1216+
typeset -h SRANDOM=local-variable
1217+
echo v=${ref/<->/integer}
1218+
echo NOT REACHED
1219+
1:Dereferring an autoload variable fails to load it if its hidden (direct)
1220+
>v=integer
1221+
>z=SRANDOM (zsh/random)
1222+
?(eval):6: Can't add module parameter `SRANDOM': local parameter exists
1223+
?(eval):zsh/random:6: error when adding parameter `SRANDOM'
1224+
?(eval):6: autoloading module zsh/random failed to define parameter: SRANDOM
1225+
1226+
typeset -n ref=SRANDOM[1,20]
1227+
echo v=${ref/<->/integer}
1228+
zmodload -u zsh/random
1229+
echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
1230+
typeset -h SRANDOM=local-variable
1231+
echo v=${ref/<->/integer}
1232+
echo NOT REACHED
1233+
1:Dereferring an autoload variable fails to load it if its hidden (subscript)
1234+
>v=integer
1235+
>z=SRANDOM (zsh/random)
1236+
?(eval):6: Can't add module parameter `SRANDOM': local parameter exists
1237+
?(eval):zsh/random:6: error when adding parameter `SRANDOM'
1238+
?(eval):6: autoloading module zsh/random failed to define parameter: SRANDOM
1239+
11821240
%clean

0 commit comments

Comments
 (0)