From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23092 invoked from network); 15 Feb 2000 16:43:02 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 15 Feb 2000 16:43:02 -0000 Received: (qmail 6795 invoked by alias); 15 Feb 2000 16:42:50 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 9750 Received: (qmail 6786 invoked from network); 15 Feb 2000 16:42:48 -0000 From: "Bart Schaefer" Message-Id: <1000215164242.ZM9804@candle.brasslantern.com> Date: Tue, 15 Feb 2000 16:42:42 +0000 X-Mailer: Z-Mail (5.0.0 30July97) To: zsh-workers@sunsite.auc.dk Subject: PATCH: safe dereference sigmsg[] array MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii 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