Testing autocommands, I see that Vim-7.2.107 (and older)
is using memory already freed when doing silly autocommands
such as:

$ touch foobar
$ valgrind ./vim -u NONE -c 'au! BufReadPre * cd /tmp' \
                         -c 'e foobar' 2> vg.log

In vg.log, I then see the following error:

==15058== Syscall param open(filename) points to unaddressable byte(s)
==15058==    at 0x40007D2: (within /lib/ld-2.8.90.so)
==15058==    by 0x805365E: open_buffer (buffer.c:130)
==15058==    by 0x8098548: do_ecmd (ex_cmds.c:3655)
==15058==    by 0x80AE8E9: do_exedit (ex_docmd.c:7557)
==15058==    by 0x80AE560: ex_edit (ex_docmd.c:7452)
==15058==    by 0x80A6FE7: do_one_cmd (ex_docmd.c:2622)
==15058==    by 0x80A4867: do_cmdline (ex_docmd.c:1096)
==15058==    by 0x80A3F00: do_cmdline_cmd (ex_docmd.c:702)
==15058==    by 0x80E8A07: exe_commands (main.c:2693)
==15058==    by 0x80E63A7: main (main.c:874)
==15058==  Address 0x54312d4 is 4 bytes inside a block of size 11 free'd
==15058==    at 0x4024E5A: free (vg_replace_malloc.c:323)
==15058==    by 0x8114D5D: vim_free (misc2.c:1631)
==15058==    by 0x80C97DF: shorten_fnames (fileio.c:5715)
==15058==    by 0x80AF1A9: ex_cd (ex_docmd.c:7942)
==15058==    by 0x80A6FE7: do_one_cmd (ex_docmd.c:2622)
==15058==    by 0x80A4867: do_cmdline (ex_docmd.c:1096)
==15058==    by 0x80CD35A: apply_autocmds_group (fileio.c:8853)
==15058==    by 0x80CCD9B: apply_autocmds_exarg (fileio.c:8481)
==15058==    by 0x80C2246: readfile (fileio.c:723)
==15058==    by 0x805365E: open_buffer (buffer.c:130)
==15058==    by 0x8098548: do_ecmd (ex_cmds.c:3655)
==15058==    by 0x80AE8E9: do_exedit (ex_docmd.c:7557)

The error is actually deeper inside readfile(...) (not sure
why valgrind stops the stack trace at open_buffer (buffer.c:130).

In readfile(), parameter fname may point to curbuf->b_ffname
or curbuf->b_fname before running autocommands (near fileio.c:715).
Some autocommands may change curbuf->b_ffname and
curbuf->b_fname (freeing and reallocating them) so after
executing autommand fname may then point to some invalid
memory, and readfile() then uses freed memory when
accessing fname.

Attached patch fixes the bug by making readfile() fail when
that happens.  Probably an error should also be reported
(see TODO comment in patch).  Please review the patch.

The same patch also fixes at least another error
when doing another silly autocommand:

$ touch foobar
$ vim -u NONE

:set autochdir
:au! BufReadPre * e!
:e foobar

==12943== Syscall param open(filename) points to unaddressable byte(s)
==12943==    at 0x40007D2: (within /lib/ld-2.8.90.so)
==12943==    by 0x805368E: open_buffer (buffer.c:130)
==12943==    by 0x809856E: do_ecmd (ex_cmds.c:3650)
==12943==    by 0x80AE90D: do_exedit (ex_docmd.c:7557)
==12943==    by 0x80AE584: ex_edit (ex_docmd.c:7452)
==12943==    by 0x80A700B: do_one_cmd (ex_docmd.c:2622)
==12943==    by 0x80A488B: do_cmdline (ex_docmd.c:1096)
==12943==    by 0x812A4F0: nv_colon (normal.c:5233)
==12943==    by 0x8123B74: normal_cmd (normal.c:1200)
==12943==    by 0x80E69B9: main_loop (main.c:1180)
==12943==    by 0x80E6506: main (main.c:939)
==12943==  Address 0x5d69824 is 4 bytes inside a block of size 11 free'd
==12943==    at 0x4024E5A: free (vg_replace_malloc.c:323)
==12943==    by 0x8114D91: vim_free (misc2.c:1631)
==12943==    by 0x80C9803: shorten_fnames (fileio.c:5715)
==12943==    by 0x805538B: do_autochdir (buffer.c:1476)
==12943==    by 0x8098521: do_ecmd (ex_cmds.c:3631)
==12943==    by 0x80AE90D: do_exedit (ex_docmd.c:7557)
==12943==    by 0x80AE584: ex_edit (ex_docmd.c:7452)
==12943==    by 0x80A700B: do_one_cmd (ex_docmd.c:2622)
==12943==    by 0x80A488B: do_cmdline (ex_docmd.c:1096)
==12943==    by 0x80CD3A9: apply_autocmds_group (fileio.c:8861)
==12943==    by 0x80CCDEA: apply_autocmds_exarg (fileio.c:8489)
==12943==    by 0x80C226A: readfile (fileio.c:723)
==12943==    by 0x805368E: open_buffer (buffer.c:130)
==12943==    by 0x809856E: do_ecmd (ex_cmds.c:3650)
==12943==    by 0x80AE90D: do_exedit (ex_docmd.c:7557)
==12943==    by 0x80AE584: ex_edit (ex_docmd.c:7452)
==12943==    by 0x80A700B: do_one_cmd (ex_docmd.c:2622)
==12943==    by 0x80A488B: do_cmdline (ex_docmd.c:1096)
==12943==    by 0x812A4F0: nv_colon (normal.c:5233)
==12943==    by 0x8123B74: normal_cmd (normal.c:1200)
==12943==    by 0x80E69B9: main_loop (main.c:1180)
==12943==    by 0x80E6506: main (main.c:939)
(and many other errors follow)

Regards
-- Dominique

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Index: fileio.c
===================================================================
RCS file: /cvsroot/vim/vim7/src/fileio.c,v
retrieving revision 1.129
diff -c -r1.129 fileio.c
*** fileio.c	31 Dec 2008 15:21:17 -0000	1.129
--- fileio.c	11 Feb 2009 21:46:59 -0000
***************
*** 69,75 ****
  static int au_find_group __ARGS((char_u *name));
  
  # define AUGROUP_DEFAULT    -1	    /* default autocmd group */
! # define AUGROUP_ERROR	    -2	    /* errornouse autocmd group */
  # define AUGROUP_ALL	    -3	    /* all autocmd groups */
  #endif
  
--- 69,75 ----
  static int au_find_group __ARGS((char_u *name));
  
  # define AUGROUP_DEFAULT    -1	    /* default autocmd group */
! # define AUGROUP_ERROR	    -2	    /* erroneous autocmd group */
  # define AUGROUP_ALL	    -3	    /* all autocmd groups */
  #endif
  
***************
*** 699,704 ****
--- 699,708 ----
  	int	m = msg_scroll;
  	int	n = msg_scrolled;
  	buf_T	*old_curbuf = curbuf;
+ 	char_u  *old_curbuf_b_ffname = curbuf->b_ffname;
+ 	char_u  *old_curbuf_b_fname = curbuf->b_fname;
+ 	int     fname_is_b_ffname = (fname == curbuf->b_ffname);
+ 	int     fname_is_b_fname = (fname == curbuf->b_fname);
  
  	/*
  	 * The file must be closed again, the autocommands may want to change
***************
*** 737,742 ****
--- 741,764 ----
  	    return FAIL;
  	}
  #endif
+     
+ 	/*
+ 	 * Don't allow the autocommands to change the buffer name (cd for example)
+ 	 * when fname is aliased to curbuf->b_ffname or curbuf->b_fname or else
+ 	 * fname gets invalidated.
+ 	 */
+ 	if (!read_stdin
+ 		&& ((fname_is_b_ffname && (old_curbuf_b_ffname != curbuf->b_ffname))
+ 		    || (fname_is_b_fname && (old_curbuf_b_fname != curbuf->b_fname))))
+ 	{
+ 	    --no_wait_return;
+ 	    msg_scroll = msg_save;
+ 	    curbuf->b_p_ro = TRUE;	/* must use "w!" now */
+ 	    /* TODO: should report an error message such as:
+ 	     * E???: *ReadPre autocommands must not change buffer name */
+ 	    return FAIL;
+ 	}
+ 
  	/*
  	 * Don't allow the autocommands to change the current buffer.
  	 * Try to re-open the file.

Raspunde prin e-mail lui