Problem:
As a workaround to the netbeans bug fixed by Vim 7.3.060 (Netbeans:
crash when socket is disconnected unexpectedly), pyclewn sends a
'DETACH' netbeans message to terminate the netbeans session instead of
just closing the socket. This causes Vim to crash when running the new
'test_bp_restored_after_detach' test from the 'pdb' pyclewn test
suite.
The crash does not occur when vim is run interactively or when vim
is run under the control of gdb, only with this automated test.
Description:
See the gdb back trace below.
1. the function netbeans_parse_messages() processes a node whose
content is:
node->buffer: "DETACH\n4:removeAnno!115 1\n"
2. node->buffer is split with 'p' at netbeans.c:681, since
node->buffer contains two messages then we have (*p != NUL)
3. nb_parse_cmd() at netbeans.c:689 processes the 'DETACH' message
that frees all the netbeans data structures
4. after returning from nb_parse_cmd(), 'p' has become a pointer to
invalidated data; it occurs that it is pointing to a NUL character,
hence the call to vim_free at netbeans.c:694 that crashes Vim
since node->buffer had already been freed by the call to
nb_parse_cmd('DETACH')
Patch:
See the attached patch on Vim 7.3.069.
=== gdb back trace ================================================
(gdb) bt
#0 0x00007f8e3ff3e1c7 in kill () from /lib/libc.so.6
#1 0x000000000050f6be in may_core_dump () at os_unix.c:3140
#2 0x000000000050f668 in mch_exit (r=1) at os_unix.c:3106
#3 0x00000000004a68ea in getout (exitval=1) at main.c:1432
#4 0x00000000004d0ccc in preserve_exit () at misc1.c:8478
#5 0x000000000050d9c5 in deathtrap (sigarg=6) at os_unix.c:1090
#6 <signal handler called>
#7 0x00007f8e3ff3ded5 in raise () from /lib/libc.so.6
#8 0x00007f8e3ff3f3f3 in abort () from /lib/libc.so.6
#9 0x00007f8e3ff7a408 in ?? () from /lib/libc.so.6
#10 0x00007f8e3ff7f9a8 in ?? () from /lib/libc.so.6
#11 0x00007f8e3ff81ab6 in free () from /lib/libc.so.6
#12 0x00000000004d4937 in vim_free (x=0xbd6bc0) at misc2.c:1699
#13 0x00000000005acb2f in netbeans_parse_messages () at netbeans.c:694
#14 0x00000000004999c6 in inchar (buf=0x8a1c4b "", maxlen=157,
wait_time=0, tb_change_cnt=235) at getchar.c:2944
#15 0x0000000000499708 in vgetorpeek (advance=0) at getchar.c:2780
#16 0x0000000000497f43 in vpeekc () at getchar.c:1796
#17 0x0000000000497fe4 in char_avail () at getchar.c:1846
#18 0x00000000004d6ed6 in update_mouseshape (shape_idx=-1) at misc2.c:3659
#19 0x000000000057dc86 in setmouse () at term.c:3348
#20 0x00000000004775ae in getcmdline (firstc=58, count=1, indent=0) at
ex_getln.c:310
#21 0x000000000047aaf2 in getexline (c=58, cookie=0x0, indent=0) at
ex_getln.c:2133
#22 0x00000000004635a0 in do_cmdline (cmdline=0x0, fgetline=0x47aab7
<getexline>, cookie=0x0, flags=0) at ex_docmd.c:1019
#23 0x00000000004ec50e in nv_colon (cap=0x7fff615cd0b0) at normal.c:5319
#24 0x00000000004e52f0 in normal_cmd (oap=0x7fff615cd180, toplevel=1)
at normal.c:1190
#25 0x00000000004a65ff in main_loop (cmdwin=0, noexmode=0) at main.c:1260
#26 0x00000000004a60df in main (argc=10, argv=0x7fff615cd478) at main.c:965
(gdb)
=======================================================================
--
Xavier
Les Chemins de Lokoti: http://lokoti.alwaysdata.net
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff --git a/src/netbeans.c b/src/netbeans.c
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -643,6 +643,7 @@
{
char_u *p;
queue_T *node;
+ int last;
while (head.next != NULL && head.next != &head)
{
@@ -679,7 +680,8 @@
* the buffer. Do this before executing, because new buffers can
* be added while busy handling the command. */
*p++ = NUL;
- if (*p == NUL)
+ last = (*p == NUL);
+ if (last)
{
head.next = node->next;
node->next->prev = node->prev;
@@ -688,13 +690,16 @@
/* now, parse and execute the commands */
nb_parse_cmd(node->buffer);
- if (*p == NUL)
+ if (last)
{
/* buffer finished, dispose of the node and buffer */
vim_free(node->buffer);
vim_free(node);
}
- else
+ /* p and node->buffer are not anymore valid pointers when the
+ * previous netbeans command processed by nb_parse_cmd() has
+ * freed the 'head' queue */
+ else if (head.next != &head)
{
/* more follows, move to the start */
STRMOVE(node->buffer, p);