diff options
author | Bart Schaefer <schaefer@zsh.org> | 2024-02-23 09:51:06 -0800 |
---|---|---|
committer | Bart Schaefer <schaefer@zsh.org> | 2024-02-23 09:51:06 -0800 |
commit | 4b9cd6b8bd5f67500e716f8485aebd31a9f7cf47 (patch) | |
tree | 5376037a7d85f0b43189308f2ea5c476fea74c55 /Src | |
parent | 40d5200c8b882708ecd411bd88760e20deec82fd (diff) | |
download | zsh-4b9cd6b8bd5f67500e716f8485aebd31a9f7cf47.tar.gz zsh-4b9cd6b8bd5f67500e716f8485aebd31a9f7cf47.tar.xz zsh-4b9cd6b8bd5f67500e716f8485aebd31a9f7cf47.zip |
52583: extra check for proper scope and existence of readonly specials
Diffstat (limited to 'Src')
-rw-r--r-- | Src/params.c | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/Src/params.c b/Src/params.c index b329d2079..225acb8a1 100644 --- a/Src/params.c +++ b/Src/params.c @@ -1004,8 +1004,29 @@ createparam(char *name, int flags) gethashnode2(paramtab, name) : paramtab->getnode(paramtab, name)); - if (oldpm && (oldpm->node.flags & PM_NAMEREF) && - !(flags & PM_NAMEREF) && (oldpm = upscope(oldpm, oldpm->base))) { + if (oldpm && (oldpm->node.flags & PM_RO_BY_DESIGN)) { + if (!(flags & PM_LOCAL)) { + /* Must call the API for namerefs and specials to work */ + pm = (Param) paramtab->getnode2(paramtab, oldpm->node.nam); + if (!pm || ((pm->node.flags & PM_NAMEREF) && + pm->level != locallevel)) { + zerr("%s: can't modify read-only parameter", name); + return NULL; + } + } + /** + * Implementation note: In the case of a readonly nameref, + * the right thing might be to insert a new global into + * the paramtab and point the local pm->old at it, rather + * than error. That is why gethashnode2() is called + * first, to avoid skipping up the stack prematurely. + **/ + } + + if (oldpm && !(flags & PM_NAMEREF) && + (!(oldpm->node.flags & PM_RO_BY_DESIGN) || !(flags & PM_LOCAL)) && + (oldpm->node.flags & PM_NAMEREF) && + (oldpm = upscope(oldpm, oldpm->base))) { Param lastpm; struct asgment stop; stop.flags = PM_NAMEREF | (flags & PM_LOCAL); |