summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilippe Altherr <philippe.altherr@gmail.com>2025-10-26 17:31:02 -0700
committerBart Schaefer <schaefer@zsh.org>2025-10-26 17:31:02 -0700
commitb66a2e2524ac0dc1794b8675292986056c5339a8 (patch)
tree00e874d1c1a4dade84c513e71f6aae8d797d241d
parent53790: corrections to reference loop detection (diff)
downloadzsh-b66a2e2524ac0dc1794b8675292986056c5339a8.tar
zsh-b66a2e2524ac0dc1794b8675292986056c5339a8.tar.gz
zsh-b66a2e2524ac0dc1794b8675292986056c5339a8.tar.bz2
zsh-b66a2e2524ac0dc1794b8675292986056c5339a8.tar.lz
zsh-b66a2e2524ac0dc1794b8675292986056c5339a8.tar.xz
zsh-b66a2e2524ac0dc1794b8675292986056c5339a8.tar.zst
zsh-b66a2e2524ac0dc1794b8675292986056c5339a8.zip
53798: report reference loops created when a reference goes out of scope
-rw-r--r--ChangeLog3
-rw-r--r--Src/params.c22
-rw-r--r--Src/zsh.h1
-rw-r--r--Test/K01nameref.ztst39
4 files changed, 49 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index ee7799f72..5785e858d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,9 @@
* Philippe: 53790: Src/builtin.c, Test/K01nameref.ztst,
Test/V10private.ztst: corrections to reference loop detection
+ * Philippe: 53798: Src/params.c, Src/zsh.h, Test/K01nameref.ztst:
+ report reference loops created when a reference goes out of scope
+
2025-10-24 Oliver Kiddle <opk@zsh.org>
* 54002: Src/parse.c: silence compiler warning for static function
diff --git a/Src/params.c b/Src/params.c
index cf6abcf48..aa948cf0c 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -6278,19 +6278,19 @@ resolve_nameref(Param pm, const Asgment stop)
if (pm && (pm->node.flags & PM_NAMEREF)) {
char *refname = GETREFNAME(pm);
- if (pm->node.flags & (PM_UNSET|PM_TAGGED)) {
+ if (pm->node.flags & PM_TAGGED) {
+ zerr("%s: invalid self reference", pm->node.nam);
+ return NULL;
+ } else if (pm->node.flags & PM_UNSET) {
/* Semaphore with createparam() */
pm->node.flags &= ~PM_UNSET;
if (pm->node.flags & PM_NEWREF) /* See setloopvar() */
return NULL;
- if (refname && *refname && (pm->node.flags & PM_TAGGED))
- pm->node.flags |= PM_SELFREF; /* See setscope() */
return (HashNode) pm;
} else if (refname) {
- if ((pm->node.flags & PM_TAGGED) ||
- (stop && strcmp(refname, stop->name) == 0)) {
+ if (stop && strcmp(refname, stop->name) == 0) {
/* zwarnnam(refname, "invalid self reference"); */
- return stop ? (HashNode)pm : NULL;
+ return (HashNode)pm;
}
if (*refname)
seek = refname;
@@ -6418,15 +6418,7 @@ setscope(Param pm)
if (basepm) {
if (basepm->node.flags & PM_NAMEREF) {
if (pm == basepm) {
- if (pm->node.flags & PM_SELFREF) {
- /* Loop signalled by resolve_nameref() */
- if (upscope(pm, pm->base) == pm) {
- zerr("%s: invalid self reference", refname);
- unsetparam_pm(pm, 0, 1);
- break;
- }
- pm->node.flags &= ~PM_SELFREF;
- } else if (pm->base == pm->level) {
+ if (pm->base == pm->level) {
if (refname && *refname &&
strcmp(pm->node.nam, refname) == 0) {
zerr("%s: invalid self reference", refname);
diff --git a/Src/zsh.h b/Src/zsh.h
index 4e5c02980..ebb63f498 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1935,7 +1935,6 @@ struct tieddata {
#define PM_NAMEDDIR (1<<29) /* has a corresponding nameddirtab entry */
#define PM_NAMEREF (1<<30) /* pointer to a different parameter */
-#define PM_SELFREF PM_UNIQUE /* Overload when namerefs resolved */
#define PM_NEWREF PM_SINGLE /* Overload in for-loop namerefs */
/* The option string corresponds to the first of the variables above */
diff --git a/Test/K01nameref.ztst b/Test/K01nameref.ztst
index bc9054093..460bc7260 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -1315,4 +1315,43 @@ F:previously this could create an infinite recursion and crash
>ref1=var2
>ref2=var2
+ typeset -n ref1
+ typeset -n ref2=ref1;
+ () {
+ typeset ref2=foo
+ ref1=ref2
+ }
+ echo reached
+ echo $ref1
+ echo NOT REACHED
+1:expansion of incidental reference loop triggers error
+>reached
+*?*: ref1: invalid self reference
+
+ typeset -n ref1
+ typeset -n ref2=ref1;
+ () {
+ typeset ref2=foo
+ ref1=ref2
+ }
+ echo reached
+ ref1=foo
+ echo NOT REACHED
+1:assignment to incidental reference loop triggers error
+>reached
+*?*: ref1: invalid self reference
+
+ typeset -n ref1
+ typeset -n ref2=ref1;
+ () {
+ typeset ref2=foo
+ ref1=ref2
+ }
+ echo reached
+ typeset -n ref3=ref1
+ echo NOT REACHED
+1:reference to incidental reference loop triggers error
+>reached
+*?*: ref1: invalid self reference
+
%clean