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

Re: menu-select interactive mode



Sorry for a log post.

At 11:50 -0700 11/04/10, Bart Schaefer wrote:
>} > There are still some bugs in the interactive mode.
>
>I just managed to hit a really alarming one.
> .... (snip)
>Now hit ESC-m to enter menu-selection.  I'm not even going to attempt
>to copy-paste the result, it's a screenful of garbage memory contents.

I did some analysis on this problem.
I think I found what is causing the problem, but do not know how to fix it.
(The zsh is the latest CVS with ./configure --enable-zsh-debug).

[1] For easier reference, the problem is shown here again:

% ls                    # in a working directory
aabb aabc aacc foo      #   which contains these 4 files
% cat foo               # foo contains the setup for completion
zmodload zsh/complist
autoload -Uz compinit
compinit
zstyle ':completion:*' menu select=off interactive
bindkey '\em' menu-select
% zsh -f
iMac% source foo
iMac%                   # gdb is attatched to this zsh: see [2] below.

----- Type "ls <TAB>"

iMac% ls
aabb  aabc  aacc  foo   # aoutolist

----- Type <TAB>

iMac% ls aabb           # automenu
aabb  aabc  aacc  foo 

----- Type <TAB> again

iMac% ls aabc
aabb  aabc  aacc  foo 

----- Type ESC-m

iMac% ./aabc            # cursor is on the second "a"
interactive: []
aabb  aabc  aacc  foo

Note that the command line is broken.

[2] It seems the problem is that the memory allocated for orgline is
freed while origline is still in use.

Attatch gdb to the above "zsh -f" (after "source foo", bafore "ls TAB"):

% ps | grep 'zsh -f'
56223 ttys000    0:00.60 zsh -f
% gdb /usr/local/bin/zsh 56223
GNU gdb 6.3.50-20050815 (Apple version gdb-1515) (Sat Jan 15 08:33:48 UTC 2011)
....
Attaching to program: `/usr/local/bin/zsh', process 56223.
Reading symbols for shared libraries +++....... done
0x00007fff85e9b984 in read ()
(gdb) p origline
$1 = 0x0

## origline is not allocated yet.
## set watchpoint for origline, and continue:

(gdb) watch origline 
Hardware watchpoint 1: origline
(gdb) cont
Continuing.

----- Type "ls <TAB>" (in the zsh being debugged)

Hardware watchpoint 1: origline

Old value = 0x0
New value = 0x1008202a8 "ls "
docomplete (lst=4) at zle_tricky.c:633
633	    origcs = zlemetacs;
(gdb)

## origline is allocated at zle_tricky.c:632 (in docomplete())
##     origline = dupstring(zlemetaline);
##
## dupsrting() uses zhalloc() to allocate origline in the heap.
##
## set watchpoint for the address 0x1008202a8 and continue:

(gdb) watch *(char*)0x1008202a8
Hardware watchpoint 2: *(char *) 4303487656
(gdb) cont
Continuing.

----- Type <TAB>
----- Type <TAB> again

Reading symbols for shared libraries . done
Hardware watchpoint 2: *(char *) 4303487656

Old value = 108 'l'
New value = 46 '.'
0x00007fffffe007db in __memcpy ()
(gdb) bt
#0  0x00007fffffe007db in __memcpy ()
#1  0x00007fff85ea3225 in __sfvwrite ()
#2  0x00007fff85ea2cfc in __vfprintf ()
#3  0x00007fff85f55ea8 in vsprintf ()
#4  0x00007fff85ed2947 in __sprintf_chk ()
#5  0x00000001001bd9c2 in do_single (m=0x10022f6f0) at compresult.c:1094
#6  0x00000001001be128 in do_menucmp (lst=4) at compresult.c:1224
#7  0x00000001001a81ef in before_complete (dummy=0x1001869d0, lst=0x7fff5fbff1ac) at compcore.c:473
#8  0x0000000100050239 in runhookdef (h=0x1001869d0, d=0x7fff5fbff1ac) at module.c:996
#9  0x0000000100167058 in docomplete (lst=4) at zle_tricky.c:617
#10 0x0000000100166663 in expandorcomplete (args=0x100187360) at zle_tricky.c:315
#11 0x00000001001662a5 in completecall (args=0x100187360) at zle_tricky.c:208
#12 0x0000000100154e09 in execzlefunc (func=0x100183938, args=0x100187360, set_bindk=0) at zle_main.c:1311
#13 0x000000010015435e in zlecore () at zle_main.c:1058
#14 0x0000000100154a16 in zleread (lp=0x1000b8970, rp=0x0, flags=3, context=0) at zle_main.c:1219
#15 0x0000000100156b3d in zle_main_entry (cmd=1, ap=0x7fff5fbff560) at zle_main.c:1874
#16 0x000000010003a70d in zleentry (cmd=1) at init.c:1374
#17 0x000000010003b439 in inputline () at input.c:281
#18 0x000000010003b272 in ingetc () at input.c:217
#19 0x000000010002efc4 in ihgetc () at hist.c:279
#20 0x0000000100043ede in gettok () at lex.c:717
#21 0x000000010004352b in zshlex () at lex.c:395
#22 0x00000001000626a2 in parse_event () at parse.c:451
#23 0x00000001000371ec in loop (toplevel=1, justonce=0) at init.c:132
#24 0x000000010003ac8a in zsh_main (argc=2, argv=0x7fff5fbff900) at init.c:1528
#25 0x0000000100000ce7 in main (argc=2, argv=0x7fff5fbff900) at ./main.c:93
(gdb)

## Here is the problem.
## The address 0x1008202a8 has been already freed, and it is now allocated
## to another variable p at compresult.c:1092 (in do_single())
##             p = (char *) zhalloc(strlen(prpre) + strlen(str) +
##
## (it is not shown in this log, but I confirmed the value of p is 0x1008202a8)
##
## But the origline is still in use.
## Set the read-watchpoint for it, and continue:

(gdb) rwatch origline
Hardware read watchpoint 3: origline
(gdb) cont
Continuing.

----- Type ESC-m

Hardware read watchpoint 3: origline

Value = 0x1008202a8 "./aabc"
0x00000001001eeb3b in domenuselect (dummy=0x0, dat=0x0) at complist.c:2404
2404	            int l = strlen(origline);
(gdb)

## domenuselect() uses origline, but it has been corrupted
## (it should be "ls "), and the command line will be broken soon.

During "menu completion", the execution of zsh returns to
zlecore() after each TAB, and freeheap() is called at zle_main.c:1102.
I guess this frees the heap stack in which origline is allocated.

In the above case, it is freed between "Type TAB" and "Type TAB again".



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