summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-07-27 22:03:50 +0200
committerBram Moolenaar <Bram@vim.org>2017-07-27 22:03:50 +0200
commitd28cc3f55d4a5a980f6ac6fa682382822a223720 (patch)
treeafbd1226f742817a8a86a8d256587bf2a93a7daf
parentab6eec3887d68c260b50b1b8f9ed95d49d9306c6 (diff)
patch 8.0.0782: using freed memory in quickfix codev8.0.0782
Problem: Using freed memory in quickfix code. (Dominique Pelle) Solution: Handle a help window differently. (Yegappan Lakshmanan)
-rw-r--r--src/buffer.c11
-rw-r--r--src/ex_cmds.c6
-rw-r--r--src/proto/buffer.pro1
-rw-r--r--src/quickfix.c18
-rw-r--r--src/testdir/test_quickfix.vim14
-rw-r--r--src/version.c2
-rw-r--r--src/window.c6
7 files changed, 44 insertions, 14 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 4dbb9e91b5..45100788b0 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -249,7 +249,7 @@ open_buffer(
netbeansFireChanges = oldFire;
#endif
/* Help buffer is filtered. */
- if (curbuf->b_help)
+ if (bt_help(curbuf))
fix_help_buffer();
}
else if (read_stdin)
@@ -5669,6 +5669,15 @@ bt_terminal(buf_T *buf)
}
/*
+ * Return TRUE if "buf" is a help buffer.
+ */
+ int
+bt_help(buf_T *buf)
+{
+ return buf != NULL && buf->b_help;
+}
+
+/*
* Return TRUE if "buf" is a "nofile", "acwrite" or "terminal" buffer.
* This means the buffer name is not a file name.
*/
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 9c84e24b15..6ec3ded90b 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -6314,7 +6314,7 @@ ex_help(exarg_T *eap)
* Re-use an existing help window or open a new one.
* Always open a new one for ":tab help".
*/
- if (!curwin->w_buffer->b_help
+ if (!bt_help(curwin->w_buffer)
#ifdef FEAT_WINDOWS
|| cmdmod.tab != 0
#endif
@@ -6325,7 +6325,7 @@ ex_help(exarg_T *eap)
wp = NULL;
else
FOR_ALL_WINDOWS(wp)
- if (wp->w_buffer != NULL && wp->w_buffer->b_help)
+ if (bt_help(wp->w_buffer))
break;
if (wp != NULL && wp->w_buffer->b_nwindows > 0)
win_enter(wp, TRUE);
@@ -6425,7 +6425,7 @@ ex_helpclose(exarg_T *eap UNUSED)
FOR_ALL_WINDOWS(win)
{
- if (win->w_buffer->b_help)
+ if (bt_help(win->w_buffer))
{
win_close(win, FALSE);
return;
diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro
index e9a37dec86..a671075363 100644
--- a/src/proto/buffer.pro
+++ b/src/proto/buffer.pro
@@ -55,6 +55,7 @@ int read_viminfo_bufferlist(vir_T *virp, int writing);
void write_viminfo_bufferlist(FILE *fp);
int bt_quickfix(buf_T *buf);
int bt_terminal(buf_T *buf);
+int bt_help(buf_T *buf);
int bt_nofile(buf_T *buf);
int bt_dontwrite(buf_T *buf);
int bt_dontwrite_msg(buf_T *buf);
diff --git a/src/quickfix.c b/src/quickfix.c
index c34e34d1ce..79cb4168d6 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -2101,7 +2101,7 @@ qf_jump(
/*
* For ":helpgrep" find a help window or open one.
*/
- if (qf_ptr->qf_type == 1 && (!curwin->w_buffer->b_help || cmdmod.tab != 0))
+ if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0))
{
win_T *wp;
@@ -2109,7 +2109,7 @@ qf_jump(
wp = NULL;
else
FOR_ALL_WINDOWS(wp)
- if (wp->w_buffer != NULL && wp->w_buffer->b_help)
+ if (bt_help(wp->w_buffer))
break;
if (wp != NULL && wp->w_buffer->b_nwindows > 0)
win_enter(wp, TRUE);
@@ -5343,10 +5343,14 @@ ex_helpgrep(exarg_T *eap)
if (eap->cmdidx == CMD_lhelpgrep)
{
- /* Find an existing help window */
- FOR_ALL_WINDOWS(wp)
- if (wp->w_buffer != NULL && wp->w_buffer->b_help)
- break;
+ /* If the current window is a help window, then use it */
+ if (bt_help(curwin->w_buffer))
+ wp = curwin;
+ else
+ /* Find an existing help window */
+ FOR_ALL_WINDOWS(wp)
+ if (bt_help(wp->w_buffer))
+ break;
if (wp == NULL) /* Help window not found */
qi = NULL;
@@ -5515,7 +5519,7 @@ ex_helpgrep(exarg_T *eap)
{
/* If the help window is not opened or if it already points to the
* correct location list, then free the new location list. */
- if (!curwin->w_buffer->b_help || curwin->w_llist == qi)
+ if (!bt_help(curwin->w_buffer) || curwin->w_llist == qi)
{
if (new_qi)
ll_free_all(&qi);
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 7b344eaad7..41e5021548 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -2287,3 +2287,17 @@ func Test_changedtick()
call Xchangedtick_tests('c')
call Xchangedtick_tests('l')
endfunc
+
+" Open multiple help windows using ":lhelpgrep
+" This test used to crash Vim
+func Test_Multi_LL_Help()
+ new | only
+ lhelpgrep window
+ lopen
+ e#
+ lhelpgrep buffer
+ call assert_equal(3, winnr('$'))
+ call assert_true(len(getloclist(1)) != 0)
+ call assert_true(len(getloclist(2)) != 0)
+ new | only
+endfunc
diff --git a/src/version.c b/src/version.c
index f62d3f05b9..da00188ce0 100644
--- a/src/version.c
+++ b/src/version.c
@@ -770,6 +770,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 782,
+/**/
781,
/**/
780,
diff --git a/src/window.c b/src/window.c
index 192721708a..948303c093 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2314,7 +2314,7 @@ win_close(win_T *win, int free_buf)
/* When closing the help window, try restoring a snapshot after closing
* the window. Otherwise clear the snapshot, it's now invalid. */
- if (win->w_buffer != NULL && win->w_buffer->b_help)
+ if (bt_help(win->w_buffer))
help_window = TRUE;
else
clear_snapshot(curtab, SNAP_HELP_IDX);
@@ -2397,7 +2397,7 @@ win_close(win_T *win, int free_buf)
&& (last_window() || curtab != prev_curtab
|| close_last_window_tabpage(win, free_buf, prev_curtab)))
{
- /* Autocommands have close all windows, quit now. Restore
+ /* Autocommands have closed all windows, quit now. Restore
* curwin->w_buffer, otherwise writing viminfo may fail. */
if (curwin->w_buffer == NULL)
curwin->w_buffer = curbuf;
@@ -6479,7 +6479,7 @@ only_one_window(void)
FOR_ALL_WINDOWS(wp)
if (wp->w_buffer != NULL
- && (!((wp->w_buffer->b_help && !curbuf->b_help)
+ && (!((bt_help(wp->w_buffer) && !bt_help(curbuf))
# ifdef FEAT_QUICKFIX
|| wp->w_p_pvw
# endif