Skip to content

Commit 4a938ac

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents 4df3f68 + 3c09722 commit 4a938ac

7 files changed

Lines changed: 171 additions & 23 deletions

File tree

src/evalfunc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11200,7 +11200,10 @@ f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv)
1120011200
/* Find the start and length of the badly spelled word. */
1120111201
len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
1120211202
if (len != 0)
11203+
{
1120311204
word = ml_get_cursor();
11205+
curwin->w_set_curswant = TRUE;
11206+
}
1120411207
}
1120511208
else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL)
1120611209
{

src/normal.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6848,6 +6848,8 @@ nv_brackets(cmdarg_T *cap)
68486848
clearopbeep(cap->oap);
68496849
break;
68506850
}
6851+
else
6852+
curwin->w_set_curswant = TRUE;
68516853
# ifdef FEAT_FOLDING
68526854
if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped)
68536855
foldOpenCursor();

src/quickfix.c

Lines changed: 91 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ static int qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *, char_u *);
144144
static char_u *qf_push_dir(char_u *, struct dir_stack_T **, int is_file_stack);
145145
static char_u *qf_pop_dir(struct dir_stack_T **);
146146
static char_u *qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *);
147+
static int qflist_valid(win_T *wp, int_u qf_id);
147148
static void qf_fmt_text(char_u *text, char_u *buf, int bufsize);
148149
static void qf_clean_dir_stack(struct dir_stack_T **);
149150
static int qf_win_pos_update(qf_info_T *qi, int old_qf_index);
@@ -177,6 +178,9 @@ static qf_info_T *ll_get_or_alloc_list(win_T *);
177178
static char_u *qf_last_bufname = NULL;
178179
static bufref_T qf_last_bufref = {NULL, 0, 0};
179180

181+
static char *e_loc_list_changed =
182+
N_("E926: Current location list was changed");
183+
180184
/*
181185
* Read the errorfile "efile" into memory, line by line, building the error
182186
* list. Set the error list's title to qf_title.
@@ -1927,6 +1931,29 @@ qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *filename)
19271931
return ds_ptr==NULL? NULL: ds_ptr->dirname;
19281932
}
19291933

1934+
/*
1935+
* Returns TRUE if a quickfix/location list with the given identifier exists.
1936+
*/
1937+
static int
1938+
qflist_valid (win_T *wp, int_u qf_id)
1939+
{
1940+
qf_info_T *qi = &ql_info;
1941+
int i;
1942+
1943+
if (wp != NULL)
1944+
{
1945+
qi = GET_LOC_LIST(wp); /* Location list */
1946+
if (qi == NULL)
1947+
return FALSE;
1948+
}
1949+
1950+
for (i = 0; i < qi->qf_listcount; ++i)
1951+
if (qi->qf_lists[i].qf_id == qf_id)
1952+
return TRUE;
1953+
1954+
return FALSE;
1955+
}
1956+
19301957
/*
19311958
* When loading a file from the quickfix, the auto commands may modify it.
19321959
* This may invalidate the current quickfix entry. This function checks
@@ -2343,22 +2370,36 @@ qf_jump_edit_buffer(
23432370
else
23442371
{
23452372
int old_qf_curlist = qi->qf_curlist;
2373+
int save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
23462374

23472375
retval = buflist_getfile(qf_ptr->qf_fnum,
23482376
(linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
2349-
if (qi != &ql_info && !win_valid_any_tab(oldwin))
2377+
2378+
if (qi != &ql_info)
23502379
{
2351-
EMSG(_("E924: Current window was closed"));
2352-
*abort = TRUE;
2353-
*opened_window = FALSE;
2380+
/*
2381+
* Location list. Check whether the associated window is still
2382+
* present and the list is still valid.
2383+
*/
2384+
if (!win_valid_any_tab(oldwin))
2385+
{
2386+
EMSG(_("E924: Current window was closed"));
2387+
*abort = TRUE;
2388+
*opened_window = FALSE;
2389+
}
2390+
else if (!qflist_valid(oldwin, save_qfid))
2391+
{
2392+
EMSG(_(e_loc_list_changed));
2393+
*abort = TRUE;
2394+
}
23542395
}
23552396
else if (old_qf_curlist != qi->qf_curlist
23562397
|| !is_qf_entry_present(qi, qf_ptr))
23572398
{
23582399
if (qi == &ql_info)
23592400
EMSG(_("E925: Current quickfix was changed"));
23602401
else
2361-
EMSG(_("E926: Current location list was changed"));
2402+
EMSG(_(e_loc_list_changed));
23622403
*abort = TRUE;
23632404
}
23642405

@@ -4065,6 +4106,7 @@ ex_cfile(exarg_T *eap)
40654106
qf_info_T *qi = &ql_info;
40664107
#ifdef FEAT_AUTOCMD
40674108
char_u *au_name = NULL;
4109+
int save_qfid;
40684110
#endif
40694111
int res;
40704112

@@ -4122,8 +4164,15 @@ ex_cfile(exarg_T *eap)
41224164
if (res >= 0 && qi != NULL)
41234165
qf_list_changed(qi, qi->qf_curlist);
41244166
#ifdef FEAT_AUTOCMD
4167+
save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
41254168
if (au_name != NULL)
41264169
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf);
4170+
/*
4171+
* Autocmd might have freed the quickfix/location list. Check whether it is
4172+
* still valid
4173+
*/
4174+
if (!qflist_valid(wp, save_qfid))
4175+
return;
41274176
#endif
41284177
if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile))
41294178
{
@@ -4149,8 +4198,11 @@ ex_vimgrep(exarg_T *eap)
41494198
char_u *p;
41504199
int fi;
41514200
qf_info_T *qi = &ql_info;
4201+
int loclist_cmd = FALSE;
41524202
#ifdef FEAT_AUTOCMD
4203+
int_u save_qfid;
41534204
qfline_T *cur_qf_start;
4205+
win_T *wp;
41544206
#endif
41554207
long lnum;
41564208
buf_T *buf;
@@ -4204,6 +4256,7 @@ ex_vimgrep(exarg_T *eap)
42044256
qi = ll_get_or_alloc_list(curwin);
42054257
if (qi == NULL)
42064258
return;
4259+
loclist_cmd = TRUE;
42074260
}
42084261

42094262
if (eap->addr_count > 0)
@@ -4274,8 +4327,9 @@ ex_vimgrep(exarg_T *eap)
42744327
mch_dirname(dirname_start, MAXPATHL);
42754328

42764329
#ifdef FEAT_AUTOCMD
4277-
/* Remember the value of qf_start, so that we can check for autocommands
4278-
* changing the current quickfix list. */
4330+
/* Remember the current values of the quickfix list and qf_start, so that
4331+
* we can check for autocommands changing the current quickfix list. */
4332+
save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
42794333
cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
42804334
#endif
42814335

@@ -4335,6 +4389,18 @@ ex_vimgrep(exarg_T *eap)
43354389
using_dummy = FALSE;
43364390

43374391
#ifdef FEAT_AUTOCMD
4392+
if (loclist_cmd)
4393+
{
4394+
/*
4395+
* Verify that the location list is still valid. An autocmd might
4396+
* have freed the location list.
4397+
*/
4398+
if (!qflist_valid(curwin, save_qfid))
4399+
{
4400+
EMSG(_(e_loc_list_changed));
4401+
goto theend;
4402+
}
4403+
}
43384404
if (cur_qf_start != qi->qf_lists[qi->qf_curlist].qf_start)
43394405
{
43404406
int idx;
@@ -4491,6 +4557,13 @@ ex_vimgrep(exarg_T *eap)
44914557
if (au_name != NULL)
44924558
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
44934559
curbuf->b_fname, TRUE, curbuf);
4560+
/*
4561+
* The QuickFixCmdPost autocmd may free the quickfix list. Check the list
4562+
* is still valid.
4563+
*/
4564+
wp = loclist_cmd ? curwin : NULL;
4565+
if (!qflist_valid(wp, save_qfid))
4566+
goto theend;
44944567
#endif
44954568

44964569
/* Jump to first match. */
@@ -5543,7 +5616,8 @@ ex_cbuffer(exarg_T *eap)
55435616
#endif
55445617

55455618
/* Must come after autocommands. */
5546-
if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer
5619+
if (eap->cmdidx == CMD_lbuffer
5620+
|| eap->cmdidx == CMD_lgetbuffer
55475621
|| eap->cmdidx == CMD_laddbuffer)
55485622
{
55495623
qi = ll_get_or_alloc_list(curwin);
@@ -5614,14 +5688,6 @@ ex_cexpr(exarg_T *eap)
56145688
#endif
56155689
int res;
56165690

5617-
if (eap->cmdidx == CMD_lexpr || eap->cmdidx == CMD_lgetexpr
5618-
|| eap->cmdidx == CMD_laddexpr)
5619-
{
5620-
qi = ll_get_or_alloc_list(curwin);
5621-
if (qi == NULL)
5622-
return;
5623-
}
5624-
56255691
#ifdef FEAT_AUTOCMD
56265692
switch (eap->cmdidx)
56275693
{
@@ -5643,6 +5709,15 @@ ex_cexpr(exarg_T *eap)
56435709
}
56445710
#endif
56455711

5712+
if (eap->cmdidx == CMD_lexpr
5713+
|| eap->cmdidx == CMD_lgetexpr
5714+
|| eap->cmdidx == CMD_laddexpr)
5715+
{
5716+
qi = ll_get_or_alloc_list(curwin);
5717+
if (qi == NULL)
5718+
return;
5719+
}
5720+
56465721
/* Evaluate the expression. When the result is a string or a list we can
56475722
* use it to fill the errorlist. */
56485723
tv = eval_expr(eap->arg, NULL);

src/testdir/test_autocmd.vim

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,10 +1178,3 @@ func Test_nocatch_wipe_dummy_buffer()
11781178
call assert_fails('lv½ /x', 'E480')
11791179
au!
11801180
endfunc
1181-
1182-
func Test_wipe_cbuffer()
1183-
sv x
1184-
au * * bw
1185-
lb
1186-
au!
1187-
endfunc

src/testdir/test_quickfix.vim

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3038,3 +3038,43 @@ func Test_lfile_crash()
30383038
call assert_fails('lfile', 'E40')
30393039
au! QuickFixCmdPre
30403040
endfunc
3041+
3042+
" The following test used to crash vim
3043+
func Test_lbuffer_crash()
3044+
sv Xtest
3045+
augroup QF_Test
3046+
au!
3047+
au * * bw
3048+
augroup END
3049+
lbuffer
3050+
augroup QF_Test
3051+
au!
3052+
augroup END
3053+
endfunc
3054+
3055+
" The following test used to crash vim
3056+
func Test_lexpr_crash()
3057+
augroup QF_Test
3058+
au!
3059+
au * * call setloclist(0, [], 'f')
3060+
augroup END
3061+
lexpr ""
3062+
augroup QF_Test
3063+
au!
3064+
augroup END
3065+
enew | only
3066+
endfunc
3067+
3068+
" The following test used to crash Vim
3069+
func Test_lvimgrep_crash()
3070+
sv Xtest
3071+
augroup QF_Test
3072+
au!
3073+
au * * call setloclist(0, [], 'f')
3074+
augroup END
3075+
lvimgrep quickfix test_quickfix.vim
3076+
augroup QF_Test
3077+
au!
3078+
augroup END
3079+
enew | only
3080+
endfunc

src/testdir/test_spell.vim

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,37 @@ func Test_wrap_search()
2828
set nospell
2929
endfunc
3030

31+
func Test_curswant()
32+
new
33+
call setline(1, ['Another plong line', 'abcdefghijklmnopq'])
34+
set spell wrapscan
35+
normal 0]s
36+
call assert_equal('plong', expand('<cword>'))
37+
normal j
38+
call assert_equal(9, getcurpos()[2])
39+
normal 0[s
40+
call assert_equal('plong', expand('<cword>'))
41+
normal j
42+
call assert_equal(9, getcurpos()[2])
43+
44+
normal 0]S
45+
call assert_equal('plong', expand('<cword>'))
46+
normal j
47+
call assert_equal(9, getcurpos()[2])
48+
normal 0[S
49+
call assert_equal('plong', expand('<cword>'))
50+
normal j
51+
call assert_equal(9, getcurpos()[2])
52+
53+
normal 1G0
54+
call assert_equal('plong', spellbadword()[0])
55+
normal j
56+
call assert_equal(9, getcurpos()[2])
57+
58+
bwipe!
59+
set nospell
60+
endfunc
61+
3162
func Test_z_equal_on_invalid_utf8_word()
3263
split
3364
set spell

src/version.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,10 @@ static char *(features[]) =
786786

787787
static int included_patches[] =
788788
{ /* Add new patch number below this line */
789+
/**/
790+
1420,
791+
/**/
792+
1419,
789793
/**/
790794
1418,
791795
/**/

0 commit comments

Comments
 (0)