Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [PATCH] Remove partial duplication of strsetfn and arrsetfn
- X-seq: zsh-workers 54340
- From: Philippe Altherr <philippe.altherr@xxxxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: Re: [PATCH] Remove partial duplication of strsetfn and arrsetfn
- Date: Sun, 12 Apr 2026 14:07:33 +0200
- Arc-authentication-results: i=1; mx.google.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=aFMIq4CKRTaxjApe87oNEDYWjnMFScrYk4RhdF6a5vY=; fh=BgAYDYpL6Ne/A5nWEMVJiHiBtrz8Imz3uf26RDwgQX4=; b=ClPK+9chzzcXlZtv5fvPkiMXJZ1s8f+M9lD7Yo6iLxa6sI9DTjxOEXflz7CJ0K7yFv eZxilGqXbyh34clO4Iq2KPX8Fsy4n5fYj2t8qPMyw6YCLSYqlMA6473SJv5qUxF8At4e Mzhfzgl2m6K5xf1Z6vPYX1bVgw0bgEglymHPeszxIVIw63S0KcIWZGCe1OaUNBF+DlgK hNv7u93SVFNEcLqi452MVfKzIRxV+XLm7LepdKcu0hr2zGdAAWJeTY5F14KBvgSU70iD BNrWKBvdcMG1tLdQxOFzpM/R+8T5Xs1Ao+bDWnL1W6Zuz6aFawBROBAMg8GRhELWXAvP HRHg==; darn=zsh.org
- Arc-seal: i=1; a=rsa-sha256; t=1775995665; cv=none; d=google.com; s=arc-20240605; b=F2/S+M2pQ5YxrhoLlWldbE7EFDVbPiayfZCd8m784PdL5/rH1ok+MmiDkhvjm0S6lU vOFZqvmBsHcw141agVhlMYecitVSJPI/OYAYwUrrnC6g5YLR70RdIjcyl8Uazj3xIfWR 2jo+7TidrqnmZF6O7eRYy0AzA28sA7NBN+HvbIbtqUGbI8bZCwFFwmfUFpgGbs8g9v5b TpccR1mCuq49kfIDbaiCg2wsiTCwIt3vAM56LUdjfAjhP7mkhRyALbBphRdElVhvJGSQ YXeZ86iuqayth7hnKXyP+0WzI7cVfiF0ru715ho/KDYa6h+9jPwKBWI2D6r1uYRPx5cH OJTg==
- Archived-at: <https://zsh.org/workers/54340>
- In-reply-to: <CAGdYchsp9teqRbp59NMVR6MS5tDj5mFqwpQE2=6b35ZY537jkA@mail.gmail.com>
- List-id: <zsh-workers.zsh.org>
- References: <CAGdYchsCNGuYJAeH=ct7U+_v119NX_Y1fZD6GvZbcn12g8E4aw@mail.gmail.com> <CAGdYchsp9teqRbp59NMVR6MS5tDj5mFqwpQE2=6b35ZY537jkA@mail.gmail.com>
Here is an updated patch that fixes the problem.
Here is a script that triggered a crash:
typeset -a a # Creates an array with pm->u.arr = NULLa[1]=() # pm->gsu.a->getfn() returns a pointer to the static nullarray, which is then stored in pm->u.arr
a=( a b c ) # Triggers a crash by trying to free the pointer to nullarray stored in pm->u.arr
The fix is to not only check that v->pm->gsu.a->setfn == arrsetfn but also that old == pm->u.arr and thus can be safely "stolen"/reused.
Philippe
diff --git a/Src/params.c b/Src/params.c
index 461e02acf..95ab97ff0 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2771,24 +2771,18 @@ assignstrvalue(Value v, char *val, int flags)
newsize = v->start + vlen + (zlen - v->end);
/* Does new size differ? */
- if (newsize != zlen || v->pm->gsu.s->setfn != strsetfn) {
+ if (newsize != zlen ||
+ v->pm->gsu.s->setfn != strsetfn || z != v->pm->u.str) {
x = (char *) zalloc(newsize + 1);
strncpy(x, z, v->start);
strcpy(x + v->start, val);
strcat(x + v->start, z + v->end);
v->pm->gsu.s->setfn(v->pm, x);
} else {
- Param pm = v->pm;
/* Size doesn't change, can limit actions to only
* overwriting bytes in already allocated string */
memcpy(z + v->start, val, vlen);
- /* Implement remainder of strsetfn */
- if (!(pm->node.flags & PM_HASHELEM) &&
- ((pm->node.flags & PM_NAMEDDIR) ||
- isset(AUTONAMEDIRS))) {
- pm->node.flags |= PM_NAMEDDIR;
- adduserdir(pm->node.nam, z, 0, 0);
- }
+ v->pm->gsu.s->setfn(v->pm, z);
}
zsfree(val);
}
@@ -2982,10 +2976,7 @@ setarrvalue(Value v, char **val)
}
if (pre_assignment_length == post_assignment_length
- && v->pm->gsu.a->setfn == arrsetfn
- /* ... and isn't something that arrsetfn() treats specially */
- && 0 == (v->pm->node.flags & (PM_SPECIAL|PM_UNIQUE))
- && NULL == v->pm->ename)
+ && v->pm->gsu.a->setfn == arrsetfn && old == v->pm->u.arr)
{
/* v->start is 0-based */
p = old + v->start;
@@ -2995,13 +2986,13 @@ setarrvalue(Value v, char **val)
/* Give away ownership of the string */
*p++ = *r++;
}
+ v->pm->gsu.a->setfn(v->pm, old);
} else {
/* arr+=( ... )
* arr[${#arr}+x,...]=( ... ) */
if (post_assignment_length > pre_assignment_length &&
pre_assignment_length <= v->start &&
- pre_assignment_length > 0 &&
- v->pm->gsu.a->setfn == arrsetfn)
+ v->pm->gsu.a->setfn == arrsetfn && old == v->pm->u.arr)
{
p = new = (char **) zrealloc(old, sizeof(char *)
* (post_assignment_length + 1));
@@ -4059,15 +4050,15 @@ strgetfn(Param pm)
mod_export void
strsetfn(Param pm, char *x)
{
- zsfree(pm->u.str);
- pm->u.str = x;
+ if (pm->u.str != x) {
+ if (pm->u.str) zsfree(pm->u.str);
+ pm->u.str = x;
+ }
if (!(pm->node.flags & PM_HASHELEM) &&
((pm->node.flags & PM_NAMEDDIR) || isset(AUTONAMEDIRS))) {
pm->node.flags |= PM_NAMEDDIR;
adduserdir(pm->node.nam, x, 0, 0);
}
- /* If you update this function, you may need to update the
- * `Implement remainder of strsetfn' block in assignstrvalue(). */
}
/* Function to get value of an array parameter */
@@ -4087,16 +4078,15 @@ arrgetfn(Param pm)
mod_export void
arrsetfn(Param pm, char **x)
{
- if (pm->u.arr && pm->u.arr != x)
- freearray(pm->u.arr);
+ if (pm->u.arr != x) {
+ if (pm->u.arr) freearray(pm->u.arr);
+ pm->u.arr = x;
+ }
if (pm->node.flags & PM_UNIQUE)
uniqarray(x);
- pm->u.arr = x;
/* Arrays tied to colon-arrays may need to fix the environment */
if (pm->ename && x)
arrfixenv(pm->ename, x);
- /* If you extend this function, update the list of conditions in
- * setarrvalue(). */
}
/* Function to get value of an association parameter */
Messages sorted by:
Reverse Date,
Date,
Thread,
Author