Re: zsh segfault bug from 5.9.1-1 onwards
Mikael Magnusson <[email protected]>
| Newsgroups | gmane.comp.shells.zsh.devel |
|---|---|
| Message-ID | <CAHYJk3R2uNBOCJ-dxnirJ7gaW54LQNo=dwn8LvhFpj4NOzJm+Q@mail.gmail.com> |
On Fri, Aug 7, 2026 at 9:25 AM Châu Trác Thịnh <[email protected]> wrote: > > I'm on Arch Linux, and a script of mine started to segfault after updating from 5.9-6 to 5.9.1-1. > > Minimal reproduction: run the following > ``` > (echo 1 | cat & (echo 2)) > ``` > > There's no segfault when: > > Reverting to 5.9-6 > removing either of the parenthesis > removing any command in the chain (replacing them can still segfault; my original code is quite different) After break fork and fiddling with set follow-fork-mode I managed to follow the correct child, Thread 4.1 "zsh" received signal SIGSEGV, Segmentation fault. 0x0000000000462cde in havefiles () at jobs.c:1620 1620 peekfirst(jobtab[i].filelist)) { (gdb) bt #0 0x0000000000462cde in havefiles () at jobs.c:1620 #1 0x00000000004394b0 in execcmd_exec (state=0x7ffcf7998710, eparams=0x7ffcf79979c0, input=0, output=0, how=18, last1=1, close_if_forked=-1) at exec.c:3719 #2 0x0000000000434bf1 in execpline2 (state=0x7ffcf7998710, pcode=707, how=18, input=0, output=0, last1=1) at exec.c:2070 #3 0x0000000000433834 in execpline (state=0x7ffcf7998710, slcode=10242, how=18, last1=1) at exec.c:1795 (gdb) p *jobtab[i].filelist $2 = {list = {first = 0x0, last = 0x22af360, flags = 0}, node = {next = 0x0, prev = 0x22af360, dat = 0x0}} As we can see here, first is NULL, and peekfirst does ->list.first->dat which crashes. The problem was introduced in zw/51404: Nullify filelist after deleting (fix segfault) d3edf318306e37d2d96. The problem isn't that it nullifies the filelist, but how it checks for that later. I think this is the fix: diff --git i/Src/jobs.c w/Src/jobs.c index 657d62ea0b..fef3c708e5 100644 --- i/Src/jobs.c +++ w/Src/jobs.c @@ -1617,7 +1617,7 @@ havefiles(void) for (i = 1; i <= maxjob; i++) if (jobtab[i].stat && jobtab[i].filelist && - peekfirst(jobtab[i].filelist)) { + nonempty(jobtab[i].filelist)) { return 1; } return 0; Which instead just checks if ->list.first == NULL. -- Mikael Magnusson