Hi Dominique and list,

2016-3-19(Sat) 10:01:43 UTC+9 h_east:
> Hi,
> 
> 2016-3-19(Sat) 5:18:03 UTC+9 Dominique Pelle:
> > Hi
> > 
> > afl-fuzz found another case that crashes
> > Vim-7.4.1591 and older.
> > 
> > $ cat > crash.vim <<EOF
> > fun R(n)
> >   wincmd p
> >   only
> > endfun
> > 
> > helpgrep quickfix
> > autocmd BufReadCmd * call R(expand("<amatch>"))
> > let s = [""]
> > let q = []
> > for w in s
> >   call add(q, {'filename': 't' })
> >   call setloclist(0, q)
> > endfor
> > lrewind
> > EOF
> > 
> > $ vim -u NONE -S crash.vim
> > Vim: Caught deadly signal SEGV
> > 
> > Vim: Finished.
> > Segmentation fault (core dumped)
> > 
> > Valgrind says:
> > 
> > ==4729== Memcheck, a memory error detector
> > ==4729== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
> > ==4729== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
> > ==4729== Command: ./vim -u NONE -S crash.vim
> > ==4729== Parent PID: 2749
> > ==4729==
> > ==4729== Invalid read of size 8
> > ==4729==    at 0x53CDF1: qf_jump (quickfix.c:1808)
> > ==4729==    by 0x49F6F7: do_one_cmd (ex_docmd.c:2921)
> > ==4729==    by 0x49F6F7: do_cmdline (ex_docmd.c:1107)
> > ==4729==    by 0x493951: do_source (ex_cmds2.c:3895)
> > ==4729==    by 0x4942EB: cmd_source (ex_cmds2.c:3508)
> > ==4729==    by 0x49F6F7: do_one_cmd (ex_docmd.c:2921)
> > ==4729==    by 0x49F6F7: do_cmdline (ex_docmd.c:1107)
> > ==4729==    by 0x43D891: exe_commands (main.c:2925)
> > ==4729==    by 0x43D891: main (main.c:955)
> > ==4729==  Address 0x10b4c0f8 is 40 bytes inside a block of size 64 free'd
> > ==4729==    at 0x4C2BDEC: free (in
> > /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> > ==4729==    by 0x53A237: qf_free (quickfix.c:2142)
> > ==4729==    by 0x53A2FC: ll_free_all (quickfix.c:953)
> > ==4729==    by 0x53C7A4: qf_free_all (quickfix.c:967)
> > ==4729==    by 0x5C0480: win_free (window.c:4726)
> > ==4729==    by 0x5C174E: win_free_mem (window.c:2614)
> > ==4729==    by 0x5C1C46: win_close (window.c:2455)
> > ==4729==    by 0x5C34C3: close_others (window.c:3429)
> > ==4729==    by 0x49F6F7: do_one_cmd (ex_docmd.c:2921)
> > ==4729==    by 0x49F6F7: do_cmdline (ex_docmd.c:1107)
> > ==4729==    by 0x474024: call_user_func (eval.c:24927)
> > ==4729==    by 0x474024: call_func (eval.c:8868)
> > ==4729==    by 0x47872F: get_func_tv (eval.c:8657)
> > ==4729==    by 0x4800FB: ex_call (eval.c:3535)
> > ==4729==    by 0x49F6F7: do_one_cmd (ex_docmd.c:2921)
> > ==4729==    by 0x49F6F7: do_cmdline (ex_docmd.c:1107)
> > ==4729==    by 0x4B52CC: apply_autocmds_group (fileio.c:9451)
> > ==4729==    by 0x4B7B77: apply_autocmds_exarg (fileio.c:9018)
> > ==4729==    by 0x4B7B77: readfile (fileio.c:383)
> > ==4729==    by 0x44517F: open_buffer (buffer.c:151)
> > ==4729==    by 0x486F8A: do_ecmd (ex_cmds.c:3768)
> > ==4729==    by 0x487330: getfile (ex_cmds.c:3190)
> > ==4729==    by 0x43FB81: buflist_getfile (buffer.c:2094)
> > ==4729==    by 0x53D026: qf_jump (quickfix.c:1798)
> > ==4729==    by 0x49F6F7: do_one_cmd (ex_docmd.c:2921)
> > ==4729==    by 0x49F6F7: do_cmdline (ex_docmd.c:1107)
> > ==4729==    by 0x493951: do_source (ex_cmds2.c:3895)
> > ==4729==    by 0x4942EB: cmd_source (ex_cmds2.c:3508)
> > ==4729==    by 0x49F6F7: do_one_cmd (ex_docmd.c:2921)
> > ==4729==    by 0x49F6F7: do_cmdline (ex_docmd.c:1107)
> > ==4729==    by 0x43D891: exe_commands (main.c:2925)
> > ==4729==    by 0x43D891: main (main.c:955)
> > (more errors after that)
> > 
> > Code in quickfix.c:
> > 
> >   1424     void
> >   1425 qf_jump(
> >   ....
> >   1797         else
> > !!1798             ok = buflist_getfile(qf_ptr->qf_fnum,
> >   1799                             (linenr_T)1, GETF_SETMARK |
> > GETF_SWITCH, forceit);
> >   1800     }
> >   1801
> >   1802     if (ok == OK)
> >   1803     {
> >   1804         /* When not switched to another buffer, still need to
> > set pc mark */
> >   1805         if (curbuf == old_curbuf)
> >   1806             setpcmark();
> >   1807
> > !!1808         if (qf_ptr->qf_pattern == NULL)
> > 
> > Memory used at line quickfix.c:1808 was previously freed
> > a few lines above at quickfix.c:1798 which triggered an
> > autocommand.
> > 
> > I don't understand the code enough to see how to fix it.
> 
> I've already written a patch.
> I am writing a test now.
> 
> Please wait for a few hours.

An attached patch may fix this problem.
I was wondering if anyone could confirm this.

Thanks.
--
Best regards,
Hirohito Higashi (a.k.a. h_east)

-- 
-- 
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

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index 3d42337..13a2ff7 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -55,6 +55,9 @@ list is destroyed.
 The following quickfix commands can be used.  The location list commands are
 similar to the quickfix commands, replacing the 'c' prefix in the quickfix
 command with 'l'.
+						*E924*
+If current window was closed by |autocommand| in the location list command
+proccess, it will be aborted.
 
 							*:cc*
 :cc[!] [nr]		Display error [nr].  If [nr] is omitted, the same
diff --git a/src/globals.h b/src/globals.h
index bd9ef5c..e3ee91b 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1511,6 +1511,7 @@ EXTERN char_u e_prev_dir[]	INIT(= N_("E459: Cannot go back to previous directory
 #ifdef FEAT_QUICKFIX
 EXTERN char_u e_quickfix[]	INIT(= N_("E42: No Errors"));
 EXTERN char_u e_loclist[]	INIT(= N_("E776: No location list"));
+EXTERN char_u e_curwinclosed[]	INIT(= N_("E924: Current window was closed"));
 #endif
 EXTERN char_u e_re_damg[]	INIT(= N_("E43: Damaged match string"));
 EXTERN char_u e_re_corr[]	INIT(= N_("E44: Corrupted regexp program"));
diff --git a/src/quickfix.c b/src/quickfix.c
index 8dfad2e..cfa8db6 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -1795,8 +1795,18 @@ win_found:
 					   oldwin == curwin ? curwin : NULL);
 	}
 	else
+	{
 	    ok = buflist_getfile(qf_ptr->qf_fnum,
 			    (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
+	    if (qi != &ql_info && !win_valid(oldwin))
+	    {
+		EMSG(_(e_curwinclosed));
+		ok = FALSE;
+		qi = NULL;
+		qf_ptr = NULL;
+	    }
+	}
+
     }
 
     if (ok == OK)
@@ -1899,7 +1909,7 @@ win_found:
 	if (opened_window)
 	    win_close(curwin, TRUE);    /* Close opened window */
 #endif
-	if (qf_ptr->qf_fnum != 0)
+	if (qf_ptr != NULL && qf_ptr->qf_fnum != 0)
 	{
 	    /*
 	     * Couldn't open file, so put index back where it was.  This could
@@ -1913,8 +1923,11 @@ failed:
 	}
     }
 theend:
-    qi->qf_lists[qi->qf_curlist].qf_ptr = qf_ptr;
-    qi->qf_lists[qi->qf_curlist].qf_index = qf_index;
+    if (qi != NULL)
+    {
+	qi->qf_lists[qi->qf_curlist].qf_ptr = qf_ptr;
+	qi->qf_lists[qi->qf_curlist].qf_index = qf_index;
+    }
 #ifdef FEAT_WINDOWS
     if (p_swb != old_swb && opened_window)
     {
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 5982aee..22a7e67 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -495,3 +495,22 @@ function Test_locationlist()
 
     augroup! testgroup
 endfunction
+
+function Test_locationlist_curwin_was_closed()
+    augroup testgroup
+      au!
+      autocmd BufReadCmd t call R(expand("<amatch>"))
+    augroup END
+
+    function R(n)
+      quit
+    endfunc
+
+    new
+    let q = []
+    call add(q, {'filename': 't' })
+    call setloclist(0, q)
+    call assert_fails('lrewind', 'E924:')
+
+    augroup! testgroup
+endfunction

Reply via email to