diff options
| author | Philippe Altherr <philippe.altherr@gmail.com> | 2025-10-26 17:31:02 -0700 |
|---|---|---|
| committer | Bart Schaefer <schaefer@zsh.org> | 2025-10-26 17:31:02 -0700 |
| commit | b66a2e2524ac0dc1794b8675292986056c5339a8 (patch) | |
| tree | 00e874d1c1a4dade84c513e71f6aae8d797d241d | |
| parent | 53790: corrections to reference loop detection (diff) | |
| download | zsh-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-- | ChangeLog | 3 | ||||
| -rw-r--r-- | Src/params.c | 22 | ||||
| -rw-r--r-- | Src/zsh.h | 1 | ||||
| -rw-r--r-- | Test/K01nameref.ztst | 39 |
4 files changed, 49 insertions, 16 deletions
@@ -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); @@ -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 |
