summaryrefslogtreecommitdiff
path: root/Src/params.c
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2024-02-23 09:51:06 -0800
committerBart Schaefer <schaefer@zsh.org>2024-02-23 09:51:06 -0800
commit4b9cd6b8bd5f67500e716f8485aebd31a9f7cf47 (patch)
tree5376037a7d85f0b43189308f2ea5c476fea74c55 /Src/params.c
parent40d5200c8b882708ecd411bd88760e20deec82fd (diff)
downloadzsh-4b9cd6b8bd5f67500e716f8485aebd31a9f7cf47.tar.gz
zsh-4b9cd6b8bd5f67500e716f8485aebd31a9f7cf47.zip
52583: extra check for proper scope and existence of readonly specials
Diffstat (limited to 'Src/params.c')
-rw-r--r--Src/params.c25
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);