Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [BUG] Zsh crashes when using autocomplete because of memory unsafety (double free)
Petr Šťastný 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) x12
> double free or corruption (out) x5
>
> Zsh crashed each time I tried it.
>
> zsh 5.8 (x86_64-pc-linux-gnu)
> ohmyzsh, commit 6152ac30bede172ba0422a8610dc796948ae1546
>
> Minimal setup:
> $ alias a='""'
> ^
>
> 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='""'<Left><Left><Left><TAB>
16: ./Src/Zle/compcore.c:1678: expecting 'x' at offset -1 of "x"""
Process 378 stopped
* thread #1, name = 'zsh', stop reason = signal SIGSEGV: invalid address (fault address: 0x7ffff6c84fff)
frame #0: 0x000000000053046e zsh`check_param(s="\x9e\x9e", set=0, test=1) at compcore.c:1127
1124 * offset "offs" into it via a global sucks badly.
1125 */
1126 for (p = s + offs; ; p--) {
-> 1127 if (*p == String || *p == Qstring) {
1128 /*
1129 * String followed by Snull (unquoted) or
1130 * QString followed by ' (quoted) indicate a nested
(lldb) bt 4
* thread #1, name = 'zsh', stop reason = signal SIGSEGV: invalid address (fault address: 0x7ffff6c84fff)
* frame #0: 0x000000000053046e zsh`check_param(s="\x9e\x9e", set=0, test=1) at compcore.c:1127
frame #1: 0x0000000000531c70 zsh`set_comp_sep at compcore.c:1698
frame #2: 0x000000000052dbba zsh`bin_compset(name="compset", argv=0x00007ffff6c85958, ops=0x00007ffffffd2358, func=0) at complete.c:1140
frame #3: 0x00000000004216e1 zsh`execbuiltin(args=0x00007ffff6c85928, assigns=0x0000000000000000, bn=0x00000000005e7c60) at builtin.c:507
(lldb) p funcstack[0]
(funcstack) $0 = {
prev = 0x00007ffffffdbe78
name = 0x00007ffff6c85160 "_alias"
filename = 0x00007ffff6c85168 "/srv/zsh/share/zsh/5.8.0.2-dev/functions/_alias"
caller = 0x00000000005a33b3 "(eval)"
flineno = 0
lineno = 1
tp = 1
}
(lldb) p funcstack[1]
(funcstack) $1 = {
prev = 0x00007361696c615f
name = 0x68737a2f7672732f <no value available>
filename = 0x7a2f65726168732f <no value available>
caller = 0x302e382e352f6873 <no value available>
flineno = 7363234093618508334
lineno = 8317708060514807413
tp = 1818320687
}
(lldb) p s
(char *) $2 = 0x00007ffff6c85a10 "\x9e\x9e"
(lldb) p offs
(int) $3 = -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})" } 0x00007361696c615f 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 = 0x00007ffff6c85170 "/share/zsh/5.8.0.2-dev/functions/_alias"
The segfault goes away when I unsetopt completeinword.
From that, I get a minimal segfault with a different backtrace:
[[[
$ lldb -- /srv/zsh/bin/zsh -f
% autoload compinit
% compinit
% setopt completeinword
% alias a='""'<Left><Left><Left><TAB>
16: ./Src/Zle/compcore.c:1678: expecting 'x' at offset -1 of "x"""
Process 3116 stopped
* thread #1, name = 'zsh', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
frame #0: 0x00007ffff7c74df2 libc.so.6`malloc_consolidate(av=0x00007ffff7db0c40) at malloc.c:4494
(lldb) bt 7
* thread #1, name = 'zsh', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
* frame #0: 0x00007ffff7c74df2 libc.so.6`malloc_consolidate(av=0x00007ffff7db0c40) at malloc.c:4494
frame #1: 0x00007ffff7c77a58 libc.so.6`_int_malloc(av=0x00007ffff7db0c40, bytes=2036) at malloc.c:3695
frame #2: 0x00007ffff7c793e3 libc.so.6`__GI___libc_malloc(bytes=2036) at malloc.c:3049
frame #3: 0x000000000048d49d zsh`zalloc(size=2036) at mem.c:966
frame #4: 0x00000000004492ff zsh`getfpfunc(s="_command_names", ksh=0x00007ffffffd0f1c, fdir=0x00007ffffffd0f08, alt_path=0x0000000000000000, test_only=0) at exec.c:6097
frame #5: 0x0000000000448d96 zsh`loadautofn(shf=0x000000000069c790, fksh=1, autol=0, current_fpath=0) at exec.c:5582
frame #6: 0x000000000044ef7c zsh`execcmd_exec(state=0x00007ffffffd2b20, eparams=0x00007ffffffd1ae8, input=0, output=0, how=18, last1=2, close_if_forked=-1) at exec.c:3433
(lldb) p funcstack[0]
(funcstack) $0 = {
prev = 0x00007ffff6cd0128
name = 0x00007ffff6ccc160 "_command_names"
filename = 0x0000000000000000 <no value available>
caller = 0x00007ffff6cd0160 "_autocd"
flineno = 0
lineno = 3
tp = 1
}
(lldb) p funcstack[1]
(funcstack) $1 = {
prev = 0x646e616d6d6f635f
name = 0x000073656d616e5f <no value available>
filename = 0x636f6c2f7273752f <no value available>
caller = 0x65726168732f6c61 <no value available>
flineno = 8388362428407314991
lineno = 7598807797348052325
tp = 779316847
}
(lldb)
]]]
% () { for 1; print -r -- $1 "$(xxd -p -r <<<${1#0x})" } 0x646e616d6d6f635f 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 = 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
«unsetopt completeinword»?
Cheers,
Daniel
Messages sorted by:
Reverse Date,
Date,
Thread,
Author