Running `zsh -fc ': ${${(PAA)p[foo]}::=x}'` in current zsh versions causes:
> "segmentation fault (core dumped) zsh -fc ': ${${(PAA)p[foo]}::=x}'
Also happens when testing with machabot:
> 19:42 <jp> > : ${${(PAA)p[foo]}::=x}
> 19:42 <machabot> jp: zsh[248]: segfault at 0 ip b7dfcda3 sp bfeb9ebc
> error 4 in libc-2.13.so[b7d84000+149000]
Add a simple `dupstring(s2)` fallback instead of pointlessly
trying to concatenate `s2` to NULL and segfaulting.
Also added indication of empty string using `(nil)`; the empty string
case should still provide a somewhat useful error message of
> zsh:1: not an identifier: (nil)
rather than
> zsh:1: not an identifier:
which is fairly confusing.
Signed-off-by: Joey Pabalinas <joeypabalinas@xxxxxxxxx>
Requested-by: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/Src/params.c b/Src/params.c
index de7730ae735a44963c..44a942296f23ddf88f 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -3004,6 +3004,8 @@ assignsparam(char *s, char *val, int flags)
int sstart, created = 0;
if (!isident(s)) {
+ if (!strcmp(s, ""))
+ s = "(nil)";
zerr("not an identifier: %s", s);
zsfree(val);
errflag |= ERRFLAG_ERROR;
diff --git a/Src/string.c b/Src/string.c
index 9e14ef94919c3e8ec5..7c24ab3c45777f31e9 100644
--- a/Src/string.c
+++ b/Src/string.c
@@ -126,9 +126,17 @@ mod_export char *
zhtricat(char const *s1, char const *s2, char const *s3)
{
char *ptr;
- size_t l1 = strlen(s1);
- size_t l2 = strlen(s2);
+ size_t l1;
+ size_t l2;
+ /* String duplicate fallback to prevent NULL derefs */
+ if (!s1 && !s2)
+ return dupstring(s3);
+ if (!s1)
+ l1 = 0, s1 = s2;
+ else
+ l1 = strlen(s1);
+ l2 = strlen(s2);
ptr = (char *)zhalloc(l1 + l2 + strlen(s3) + 1);
strcpy(ptr, s1);
strcpy(ptr + l1, s2);
@@ -144,8 +152,12 @@ dyncat(const char *s1, const char *s2)
{
/* This version always uses space from the current heap. */
char *ptr;
- size_t l1 = strlen(s1);
+ size_t l1;
+ /* String duplicate fallback to prevent NULL derefs */
+ if (!s1)
+ return dupstring(s2);
+ l1 = strlen(s1);
ptr = (char *)zhalloc(l1 + strlen(s2) + 1);
strcpy(ptr, s1);
strcpy(ptr + l1, s2);
@@ -158,8 +170,12 @@ bicat(const char *s1, const char *s2)
{
/* This version always uses permanently-allocated space. */
char *ptr;
- size_t l1 = strlen(s1);
+ size_t l1;
+ /* String duplicate fallback to prevent NULL derefs */
+ if (!s1)
+ return dupstring(s2);
+ l1 = strlen(s1);
ptr = (char *)zalloc(l1 + strlen(s2) + 1);
strcpy(ptr, s1);
strcpy(ptr + l1, s2);
diff --git a/Src/subst.c b/Src/subst.c
index d027e3d83cadc631a7..9a8c635e313687d046 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3150,6 +3150,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
}
if (*itype_end(s, IIDENT, 0)) {
untokenize(s);
+ if (!strcmp(s, " "))
+ s = "(nil)";
zerr("not an identifier: %s", s);
return NULL;
}
@@ -3210,6 +3212,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
++s;
if (*itype_end(s, IIDENT, 0)) {
untokenize(s);
+ if (!strcmp(s, ""))
+ s = "(nil)";
zerr("not an identifier: %s", s);
return NULL;
}
--
2.15.1
Attachment:
signature.asc
Description: PGP signature