# HG changeset patch # User Christian Brabandt # Date 1501186503 -7200 # Node ID 5ceaecedbad23636377f7653b47e33952c5d1397 # Parent 4614433e6af66382f6c5e505505250bf0651ea15 patch 8.0.0782: using freed memory in quickfix code commit https://github.com/vim/vim/commit/d28cc3f55d4a5a980f6ac6fa682382822a223720 Author: Bram Moolenaar Date: Thu Jul 27 22:03:50 2017 +0200 patch 8.0.0782: using freed memory in quickfix code Problem: Using freed memory in quickfix code. (Dominique Pelle) Solution: Handle a help window differently. (Yegappan Lakshmanan) diff --git a/src/buffer.c b/src/buffer.c --- 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 --- 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 --- a/src/proto/buffer.pro +++ b/src/proto/buffer.pro @@ -55,6 +55,7 @@ int read_viminfo_bufferlist(vir_T *virp, 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 --- 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 --- 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 --- 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 --- 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