Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: safe dereference sigmsg[] array



This came up in a discussion with someone at Sun.  A new OS version may
introduce new signal numbers; if an old zsh binary is running on such an
OS, delivery of one of the new signals to a child process can cause zsh
to segfault printing the job description.

Similarly (and where it came up in practice) if zsh's signal.h-finding
configure code doesn't look in the right places, the sigmsg[] array will
be (nearly) empty and zsh segfaults on any child status change other than
simple exit.

The following causes signames2.awk to omit a macro wrapper for the array
references that uses "unknown signal" as the message for signals greater
than SIGCOUNT.

Index: Src/jobs.c
===================================================================
@@ -615,7 +615,7 @@
 	if (pn->status != SP_RUNNING) {
 	    if (WIFSIGNALED(pn->status)) {
 		sig = WTERMSIG(pn->status);
-		llen = strlen(sigmsg[sig]);
+		llen = strlen(sigmsg(sig));
 		if (WCOREDUMP(pn->status))
 		    llen += 14;
 		if (llen > len)
@@ -626,8 +626,8 @@
 		    doputnl = 1;
 	    } else if (WIFSTOPPED(pn->status)) {
 		sig = WSTOPSIG(pn->status);
-		if ((int)strlen(sigmsg[sig]) > len)
-		    len = strlen(sigmsg[sig]);
+		if ((int)strlen(sigmsg(sig)) > len)
+		    len = strlen(sigmsg(sig));
 		if (job == thisjob && sig == SIGTSTP)
 		    doputnl = 1;
 	    } else if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
@@ -695,13 +695,13 @@
 		else
 		    fprintf(fout, "done%*s", len - 4 + 2, "");
 	    } else if (WIFSTOPPED(pn->status))
-		fprintf(fout, "%-*s", len + 2, sigmsg[WSTOPSIG(pn->status)]);
+		fprintf(fout, "%-*s", len + 2, sigmsg(WSTOPSIG(pn->status)));
 	    else if (WCOREDUMP(pn->status))
 		fprintf(fout, "%s (core dumped)%*s",
-			sigmsg[WTERMSIG(pn->status)],
-			(int)(len - 14 + 2 - strlen(sigmsg[WTERMSIG(pn->status)])), "");
+			sigmsg(WTERMSIG(pn->status)),
+			(int)(len - 14 + 2 - strlen(sigmsg(WTERMSIG(pn->status)))), "");
 	    else
-		fprintf(fout, "%-*s", len + 2, sigmsg[WTERMSIG(pn->status)]);
+		fprintf(fout, "%-*s", len + 2, sigmsg(WTERMSIG(pn->status)));
 	    for (; pn != qn; pn = pn->next)
 		fprintf(fout, (pn->next) ? "%s | " : "%s", pn->text);
 	    putc('\n', fout);
Index: Src/signames2.awk
===================================================================
@@ -63,7 +63,10 @@
     printf "#include %czsh.mdh%c\n", 34, 34
     printf "\n"
     printf "/**/\n"
-    printf "mod_export char *sigmsg[SIGCOUNT+2] = {\n"
+    printf "#define sigmsg(sig) ((sig) <= SIGCOUNT ? sig_msg[sig] : %c%s%c)", 34, "unknown signal", 34
+    printf "\n"
+    printf "/**/\n"
+    printf "mod_export char *sig_msg[SIGCOUNT+2] = {\n"
     printf "\t%c%s%c,\n", 34, "done", 34
 
     for (i = 1; i <= 0 + max; i++)
Index: Src/Modules/parameter.c
===================================================================
@@ -1230,12 +1230,12 @@
 	    else
 		state = "done";
 	} else if (WIFSTOPPED(pn->status))
-	    state = sigmsg[WSTOPSIG(pn->status)];
+	    state = sigmsg(WSTOPSIG(pn->status));
 	else if (WCOREDUMP(pn->status))
 	    sprintf((state = buf2), "%s (core dumped)",
-		    sigmsg[WTERMSIG(pn->status)]);
+		    sigmsg(WTERMSIG(pn->status)));
 	else
-	    state = sigmsg[WTERMSIG(pn->status)];
+	    state = sigmsg(WTERMSIG(pn->status));
 
 	sprintf(buf, ":%d=%s", pn->pid, state);
 

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com



Messages sorted by: Reverse Date, Date, Thread, Author