vim-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)
d28cc3f55d
This commit is contained in:
Jan Edmund Lazo 2018-09-06 05:08:15 -04:00
parent bb519fb261
commit dc15dcffad
5 changed files with 47 additions and 17 deletions

View File

@ -252,7 +252,7 @@ open_buffer (
msg_silent = old_msg_silent; msg_silent = old_msg_silent;
// Help buffer is filtered. // Help buffer is filtered.
if (curbuf->b_help) { if (bt_help(curbuf)) {
fix_help_buffer(); fix_help_buffer();
} }
} else if (read_stdin) { } else if (read_stdin) {
@ -4930,6 +4930,12 @@ chk_modeline (
return retval; return retval;
} }
// Return true if "buf" is a help buffer.
bool bt_help(const buf_T *const buf)
{
return buf != NULL && buf->b_help;
}
/* /*
* Return special buffer name. * Return special buffer name.
* Returns NULL when the buffer has a normal file name. * Returns NULL when the buffer has a normal file name.

View File

@ -4514,7 +4514,7 @@ void ex_help(exarg_T *eap)
* Re-use an existing help window or open a new one. * Re-use an existing help window or open a new one.
* Always open a new one for ":tab help". * Always open a new one for ":tab help".
*/ */
if (!curwin->w_buffer->b_help if (!bt_help(curwin->w_buffer)
|| cmdmod.tab != 0 || cmdmod.tab != 0
) { ) {
if (cmdmod.tab != 0) { if (cmdmod.tab != 0) {
@ -4522,7 +4522,7 @@ void ex_help(exarg_T *eap)
} else { } else {
wp = NULL; wp = NULL;
FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) { FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) {
if (wp2->w_buffer != NULL && wp2->w_buffer->b_help) { if (bt_help(wp2->w_buffer)) {
wp = wp2; wp = wp2;
break; break;
} }
@ -5509,7 +5509,7 @@ static int next_sign_typenr = 1;
void ex_helpclose(exarg_T *eap) void ex_helpclose(exarg_T *eap)
{ {
FOR_ALL_WINDOWS_IN_TAB(win, curtab) { FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
if (win->w_buffer->b_help) { if (bt_help(win->w_buffer)) {
win_close(win, FALSE); win_close(win, FALSE);
return; return;
} }

View File

@ -1839,12 +1839,12 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit)
/* /*
* For ":helpgrep" find a help window or open one. * 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 = NULL; win_T *wp = NULL;
if (cmdmod.tab == 0) { if (cmdmod.tab == 0) {
FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) { FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) {
if (wp2->w_buffer != NULL && wp2->w_buffer->b_help) { if (bt_help(wp2->w_buffer)) {
wp = wp2; wp = wp2;
break; break;
} }
@ -4721,16 +4721,26 @@ void ex_helpgrep(exarg_T *eap)
p_cpo = empty_option; p_cpo = empty_option;
if (eap->cmdidx == CMD_lhelpgrep) { if (eap->cmdidx == CMD_lhelpgrep) {
qi = NULL; win_T *wp = NULL;
/* Find an existing help window */ // If the current window is a help window, then use it
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (bt_help(curwin->w_buffer)) {
if (wp->w_buffer != NULL && wp->w_buffer->b_help) { wp = curwin;
} else {
// Find an existing help window
FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) {
if (bt_help(wp2->w_buffer)) {
wp = wp2;
break;
}
}
}
if (wp == NULL) { // Help window not found
qi = NULL;
} else {
qi = wp->w_llist; qi = wp->w_llist;
} }
}
/* Help window not found */
if (qi == NULL) { if (qi == NULL) {
/* Allocate a new location list for help text matches */ /* Allocate a new location list for help text matches */
qi = ll_new_list(); qi = ll_new_list();
@ -4851,7 +4861,7 @@ void ex_helpgrep(exarg_T *eap)
if (eap->cmdidx == CMD_lhelpgrep) { if (eap->cmdidx == CMD_lhelpgrep) {
/* If the help window is not opened or if it already points to the /* If the help window is not opened or if it already points to the
* correct location list, then free the new location list. */ * 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) if (new_qi)
ll_free_all(&qi); ll_free_all(&qi);
} else if (curwin->w_llist == NULL) } else if (curwin->w_llist == NULL)

View File

@ -2269,3 +2269,17 @@ func Test_changedtick()
call Xchangedtick_tests('c') call Xchangedtick_tests('c')
call Xchangedtick_tests('l') call Xchangedtick_tests('l')
endfunc 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

View File

@ -1902,7 +1902,7 @@ int win_close(win_T *win, int free_buf)
/* When closing the help window, try restoring a snapshot after closing /* When closing the help window, try restoring a snapshot after closing
* the window. Otherwise clear the snapshot, it's now invalid. */ * 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; help_window = TRUE;
else else
clear_snapshot(curtab, SNAP_HELP_IDX); clear_snapshot(curtab, SNAP_HELP_IDX);
@ -1967,8 +1967,8 @@ int win_close(win_T *win, int free_buf)
if (only_one_window() && win_valid(win) && win->w_buffer == NULL if (only_one_window() && win_valid(win) && win->w_buffer == NULL
&& (last_window() || curtab != prev_curtab && (last_window() || curtab != prev_curtab
|| close_last_window_tabpage(win, free_buf, 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 ShaDa file may fail. */ // curwin->w_buffer, otherwise writing ShaDa file may fail.
if (curwin->w_buffer == NULL) if (curwin->w_buffer == NULL)
curwin->w_buffer = curbuf; curwin->w_buffer = curbuf;
getout(0); getout(0);
@ -5341,7 +5341,7 @@ bool only_one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
int count = 0; int count = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer != NULL if (wp->w_buffer != NULL
&& (!((wp->w_buffer->b_help && !curbuf->b_help) && (!((bt_help(wp->w_buffer) && !bt_help(curbuf))
|| wp->w_p_pvw) || wp == curwin) && wp != aucmd_win) { || wp->w_p_pvw) || wp == curwin) && wp != aucmd_win) {
count++; count++;
} }