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

recipe for a ZLE segfault

$ zsh-3.1.4 -f
londo% bindkey -v
londo% bindkey '^[[A' history-beginning-search-backward

Now type ^[kBBC^[[A^M (ESC k B B C Up-arrow Enter). BLAM!

It's very specific. It has to be a history-beginning-search-backward within
vi-change-eol, and it doesn't happen if the vi-change-eol is terminated by a
switch to vi-cmd-mode. Took me a long time to pin this one down.

Test system is i486-linux with libc6.0.6, and the configuration options, as
far as I can remember them since I didn't save them anywhere, are:
./configure --prefix=/usr --enable-zsh-debug --enable-dynamic
(I assume --enable-dynamic refers to zle.so, and I do have a zle.so, amongst

Here's a backtrace at the segfault:
#0  0x40058ee8 in chunk_free ()
#1  0x40058e91 in __cfree ()
#2  0x806fed0 in zsfree (
    p=0x400abaf4 "¿F\n\b¿F\n\bôº\n@ôº\n@üº\n@üº\n@\004»\n@\004»\n@\f»\n@\f»\n@\024»\n@\024»\n@\034»\n@\034»\n@$»\n@$»\n@,»\n@,»\n@4»\n@4»\n@<»\n@<»\n@D»\n@D»\n@L»\n@L»\n@T»\n@T»\n@\\»\n@\\»\n@d»\n@d»\n@l»\n@l»\n@t»\n@t»\n@|»\n@|»\n@\204»\n@\204»\n@\214»\n@\214»\n@\224»\n@\224»\n@\234»\n@\234»\n@ñ»\n@ñ»\n@¼»\n@¼»\n@"...) at mem.c:1251
#3  0x400e3f88 in freechanges (p=0x80a46b0) at zle_utils.c:468
#4  0x400e3f38 in freeundo () at zle_utils.c:456
#5  0x400d3ab2 in zleread (lp=0x8098390 "%m%# ", rp=0x0, ha=1) at zle_main.c:536
#6  0x8066e0b in inputline () at input.c:252
#7  0x8066d15 in ingetc () at input.c:208
#8  0x80629d9 in hgetc () at hist.c:206
#9  0x806a2f9 in gettok () at lex.c:525
#10 0x8069c69 in yylex () at lex.c:288
#11 0x8074b3c in parse_event () at parse.c:99
#12 0x80654be in loop (toplevel=1, justonce=0) at init.c:96
#13 0x804f4e1 in main (argc=2, argv=0xbffffaa8) at ./main.c:77

And some more of my investigation:
(gdb) up 4
#4  0x400e3f38 in freeundo () at zle_utils.c:456
456         freechanges(nextchanges);
(gdb) p nextchanges
$1 = (struct change *) 0x80a46b0
(gdb) p *nextchanges
$2 = {prev = 0x400abaec, next = 0x400abaec, flags = 0, hist = 2, off = 8,
  del = 0x80a4360 "'\e[A' history-beginning-search-backward", ins = 0x0}
(gdb) p *nextchanges->next
$3 = {prev = 0x400abae4, next = 0x400abae4, flags = 134891176, hist = 134891176, off = 1074445044,

[bunch of garbage snipped]

(gdb) p/x *nextchanges->next
$4 = {prev = 0x400abae4, next = 0x400abae4, flags = 0x80a46a8, hist = 0x80a46a8, off = 0x400abaf4,
  del = 0x400abaf4, ins = 0x400abafc}

So basically, a bunch of pointers have gotten where they shouldn't be. At
this point I read all the code touching "nextchanges", and decided I would
not be understanding it any time soon, so here you are...

Oh, I just got another idea. MALLOC_CHECK_ might help us.

[Time passes...]

[Your sword is no longer glowing]

Well, similar results are achieved with MALLOC_CHECK_=2. Except, now, at the
abort(), the first few chars of nextchanges->del have been overwritten with
some garbage. The corruption must be earlier, and slipping past the malloc
checker. Now, seriously this time, I'm out of clever ideas, so here's your
bug report.

Alan Curry

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