From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 8739 invoked from network); 26 Jun 2020 16:24:57 -0000 Received: from ns1.primenet.com.au (HELO primenet.com.au) (203.24.36.2) by inbox.vuxu.org with ESMTPUTF8; 26 Jun 2020 16:24:57 -0000 Received: (qmail 16841 invoked by alias); 26 Jun 2020 16:24:50 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: Sender: zsh-workers@zsh.org X-Seq: 46122 Received: (qmail 4680 invoked by uid 1010); 26 Jun 2020 16:24:50 -0000 X-Qmail-Scanner-Diagnostics: from wout1-smtp.messagingengine.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.102.3/25850. spamassassin: 3.4.4. Clear:RC:0(64.147.123.24):SA:0(-2.6/5.0):. Processed in 4.646523 secs); 26 Jun 2020 16:24:50 -0000 X-Envelope-From: d.s@daniel.shahaf.name X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: none (ns1.primenet.com.au: domain at daniel.shahaf.name does not designate permitted sender hosts) X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduhedrudeluddguddtfecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvuffkjghfofggtgfgsehtqhdttdertdejnecuhfhrohhmpeffrghn ihgvlhcuufhhrghhrghfuceougdrshesuggrnhhivghlrdhshhgrhhgrfhdrnhgrmhgvqe enucggtffrrghtthgvrhhnpefhtdetfeehveeutdehuddtieefgeettedtjedtffehudei ieejleetteekudetheenucfkphepjeelrddujeeirdefledrieelnecuvehluhhsthgvrh fuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepugdrshesuggrnhhivghlrdhs hhgrhhgrfhdrnhgrmhgv X-ME-Proxy: Date: Fri, 26 Jun 2020 16:24:05 +0000 From: Daniel Shahaf To: Petr =?UTF-8?B?xaDFpWFzdG7DvQ==?= Cc: zsh-workers@zsh.org Subject: Re: [BUG] Zsh crashes when using autocomplete because of memory unsafety (double free) Message-ID: <20200626162405.4a7d28c1@tarpaulin.shahaf.local2> In-Reply-To: <00cb28e8-004e-2c8c-e02d-6063f4079c1d@soptik.tech> References: <00cb28e8-004e-2c8c-e02d-6063f4079c1d@soptik.tech> X-Mailer: Claws Mail 3.17.3 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Petr =C5=A0=C5=A5astn=C3=BD wrote on Fri, 26 Jun 2020 17:03 +0200: > Note: I'm using ohmyzsh to provide autocomplete and I can't reproduce it > without ohmyzsh, but since ohmyzsh is written entirely in shell, this > should be an issue in zsh itself. > > When I trigger autocomplete in one position, zsh crashes, yielding one > of the following messages, seemingly at random: > > (none, zsh crashes silently)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 x12 > double free or corruption (out)=C2=A0=C2=A0=C2=A0=C2=A0 x5 > > Zsh crashed each time I tried it. > > zsh 5.8 (x86_64-pc-linux-gnu) > ohmyzsh, commit 6152ac30bede172ba0422a8610dc796948ae1546 > > Minimal setup: > $ alias a=3D'""' > =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0 ^ > > Place cursor so it stands on the first " character and press Tab to > trigger autocomplete. Zsh crashes. > > I have almost default ohmyzsh installation, the only thing I changed is > theme (to `mrtazz`) and `git` plugin, none of which should affect this. > Zsh config itself (after being modified by ohmyzsh) is unchanged, if one > doesn't count `PATH` exports. Thus I don't see the need to attach my > full config. If anyone has troubles reproducing this, let me know. But > it should be enough to have ohmyzsh installed. > tl;dr: I can reproduce two different segfaults here: one of them with a minimal reproduction recipe; one with my personal setup, and a specific setopt makes it go away. With personal setup with current master: [[[ % alias a=3D'""' 16: ./Src/Zle/compcore.c:1678: expecting 'x' at offset -1 of "x""" Process 378 stopped * thread #1, name =3D 'zsh', stop reason =3D signal SIGSEGV: invalid addres= s (fault address: 0x7ffff6c84fff) frame #0: 0x000000000053046e zsh`check_param(s=3D"\x9e\x9e", set=3D0, t= est=3D1) at compcore.c:1127 1124 * offset "offs" into it via a global sucks badly. 1125 */ 1126 for (p =3D s + offs; ; p--) { -> 1127 if (*p =3D=3D String || *p =3D=3D Qstring) { 1128 /* 1129 * String followed by Snull (unquoted) or 1130 * QString followed by ' (quoted) indicate a nested (lldb) bt 4 * thread #1, name =3D 'zsh', stop reason =3D signal SIGSEGV: invalid addres= s (fault address: 0x7ffff6c84fff) * frame #0: 0x000000000053046e zsh`check_param(s=3D"\x9e\x9e", set=3D0, t= est=3D1) at compcore.c:1127 frame #1: 0x0000000000531c70 zsh`set_comp_sep at compcore.c:1698 frame #2: 0x000000000052dbba zsh`bin_compset(name=3D"compset", argv=3D0= x00007ffff6c85958, ops=3D0x00007ffffffd2358, func=3D0) at complete.c:1140 frame #3: 0x00000000004216e1 zsh`execbuiltin(args=3D0x00007ffff6c85928,= assigns=3D0x0000000000000000, bn=3D0x00000000005e7c60) at builtin.c:507 (lldb) p funcstack[0] (funcstack) $0 =3D { prev =3D 0x00007ffffffdbe78 name =3D 0x00007ffff6c85160 "_alias" filename =3D 0x00007ffff6c85168 "/srv/zsh/share/zsh/5.8.0.2-dev/functions= /_alias" caller =3D 0x00000000005a33b3 "(eval)" flineno =3D 0 lineno =3D 1 tp =3D 1 } (lldb) p funcstack[1] (funcstack) $1 =3D { prev =3D 0x00007361696c615f name =3D 0x68737a2f7672732f filename =3D 0x7a2f65726168732f caller =3D 0x302e382e352f6873 flineno =3D 7363234093618508334 lineno =3D 8317708060514807413 tp =3D 1818320687 } (lldb) p s (char *) $2 =3D 0x00007ffff6c85a10 "\x9e\x9e" (lldb) p offs (int) $3 =3D -1 ]]] In frame #0's actual arguments, 0x9e is Dnull. funcstack[1] appears to be a memory block comprising some strings (reversed because I'm on a little-endian platform): . % () { for 1; print -r -- $1 "$(xxd -p -r <<<${1#0x})" } 0x00007361696c= 615f 0x68737a2f7672732f 0x7a2f65726168732f 0x302e382e352f6873 0x00007361696c615f saila_ 0x68737a2f7672732f hsz/vrs/ 0x7a2f65726168732f z/erahs/ 0x302e382e352f6873 0.8.5/hs % xxd -p -r <<<$(printf %x 7363234093618508334); echo f/ved-2. % xxd -p -r <<<$(printf %x 8317708060514807413); echo snoitcnu % xxd -p -r <<<$(printf %x 1818320687); echo la_/ (lldb) p (char*) &funcstack[1].filename (char *) $0 =3D 0x00007ffff6c85170 "/share/zsh/5.8.0.2-dev/functions/_a= lias" The segfault goes away when I unsetopt completeinword. =46rom that, I get a minimal segfault with a different backtrace: [[[ $ lldb -- /srv/zsh/bin/zsh -f % autoload compinit % compinit % setopt completeinword % alias a=3D'""' 16: ./Src/Zle/compcore.c:1678: expecting 'x' at offset -1 of "x""" Process 3116 stopped * thread #1, name =3D 'zsh', stop reason =3D signal SIGSEGV: invalid addres= s (fault address: 0x0) frame #0: 0x00007ffff7c74df2 libc.so.6`malloc_consolidate(av=3D0x00007f= fff7db0c40) at malloc.c:4494 (lldb) bt 7 * thread #1, name =3D 'zsh', stop reason =3D signal SIGSEGV: invalid addres= s (fault address: 0x0) * frame #0: 0x00007ffff7c74df2 libc.so.6`malloc_consolidate(av=3D0x00007f= fff7db0c40) at malloc.c:4494 frame #1: 0x00007ffff7c77a58 libc.so.6`_int_malloc(av=3D0x00007ffff7db0= c40, bytes=3D2036) at malloc.c:3695 frame #2: 0x00007ffff7c793e3 libc.so.6`__GI___libc_malloc(bytes=3D2036)= at malloc.c:3049 frame #3: 0x000000000048d49d zsh`zalloc(size=3D2036) at mem.c:966 frame #4: 0x00000000004492ff zsh`getfpfunc(s=3D"_command_names", ksh=3D= 0x00007ffffffd0f1c, fdir=3D0x00007ffffffd0f08, alt_path=3D0x000000000000000= 0, test_only=3D0) at exec.c:6097 frame #5: 0x0000000000448d96 zsh`loadautofn(shf=3D0x000000000069c790, f= ksh=3D1, autol=3D0, current_fpath=3D0) at exec.c:5582 frame #6: 0x000000000044ef7c zsh`execcmd_exec(state=3D0x00007ffffffd2b2= 0, eparams=3D0x00007ffffffd1ae8, input=3D0, output=3D0, how=3D18, last1=3D2= , close_if_forked=3D-1) at exec.c:3433 (lldb) p funcstack[0] (funcstack) $0 =3D { prev =3D 0x00007ffff6cd0128 name =3D 0x00007ffff6ccc160 "_command_names" filename =3D 0x0000000000000000 caller =3D 0x00007ffff6cd0160 "_autocd" flineno =3D 0 lineno =3D 3 tp =3D 1 } (lldb) p funcstack[1] (funcstack) $1 =3D { prev =3D 0x646e616d6d6f635f name =3D 0x000073656d616e5f filename =3D 0x636f6c2f7273752f caller =3D 0x65726168732f6c61 flineno =3D 8388362428407314991 lineno =3D 7598807797348052325 tp =3D 779316847 } (lldb)=20 ]]] % () { for 1; print -r -- $1 "$(xxd -p -r <<<${1#0x})" } 0x646e616d6d6f= 635f 0x000073656d616e5f 0x636f6c2f7273752f 0x65726168732f6c61 0x646e616d6d6f635f dnammoc_ 0x000073656d616e5f seman_ 0x636f6c2f7273752f col/rsu/ 0x65726168732f6c61 erahs/la % for 1 in 8388362428407314991 7598807797348052325 779316847 ; { xxd -p= -r <<<$(printf %x $1) | xxd } 00000000: 7469 732f 6873 7a2f tis/hsz/ 00000000: 6974 636e 7566 2d65 itcnuf-e 00000000: 2e73 6e6f .sno (lldb) p (char*)&funcstack[1].filename (char *) $6 =3D 0x00007ffff6ccc170 "/usr/local/share/zsh/site-functions= .zwc" I can reproduce this latter variant in 5.7.1 as well. I haven't tried older versions. I haven't tried reproducing the issue under ohmyzsh. It could in theory be a different one. Petr, could you please check whether the issue reproduces if you =C2=ABunsetopt completeinword=C2=BB? Cheers, Daniel