Skip to content

Commit d106e5b

Browse files
committed
patch 7.4.1768
Problem: Arguments of setqflist() are not checked properly. Solution: Add better checks, add a test. (Nikolai Pavlov, Hirohito Higashi, closes #661)
1 parent 4adfaab commit d106e5b

3 files changed

Lines changed: 107 additions & 11 deletions

File tree

src/eval.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ static char *e_listarg = N_("E686: Argument of %s must be a List");
9898
static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary");
9999
static char *e_listreq = N_("E714: List required");
100100
static char *e_dictreq = N_("E715: Dictionary required");
101+
static char *e_stringreq = N_("E928: String required");
101102
static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
102103
static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
103104
static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
@@ -18280,8 +18281,9 @@ set_qf_ll_list(
1828018281
typval_T *rettv)
1828118282
{
1828218283
#ifdef FEAT_QUICKFIX
18284+
static char *e_invact = N_("E927: Invalid action: '%s'");
1828318285
char_u *act;
18284-
int action = ' ';
18286+
int action = 0;
1828518287
#endif
1828618288

1828718289
rettv->vval.v_number = -1;
@@ -18298,11 +18300,17 @@ set_qf_ll_list(
1829818300
act = get_tv_string_chk(action_arg);
1829918301
if (act == NULL)
1830018302
return; /* type error; errmsg already given */
18301-
if (*act == 'a' || *act == 'r')
18303+
if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL)
1830218304
action = *act;
18305+
else
18306+
EMSG2(_(e_invact), act);
1830318307
}
18308+
else if (action_arg->v_type == VAR_UNKNOWN)
18309+
action = ' ';
18310+
else
18311+
EMSG(_(e_stringreq));
1830418312

18305-
if (l != NULL && set_errorlist(wp, l, action,
18313+
if (l != NULL && action && set_errorlist(wp, l, action,
1830618314
(char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK)
1830718315
rettv->vval.v_number = 0;
1830818316
}

src/testdir/test_quickfix.vim

Lines changed: 94 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ endfunction
501501
function Test_locationlist_curwin_was_closed()
502502
augroup testgroup
503503
au!
504-
autocmd BufReadCmd t call R(expand("<amatch>"))
504+
autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
505505
augroup END
506506

507507
function! R(n)
@@ -510,7 +510,7 @@ function Test_locationlist_curwin_was_closed()
510510

511511
new
512512
let q = []
513-
call add(q, {'filename': 't' })
513+
call add(q, {'filename': 'test_curwin.txt' })
514514
call setloclist(0, q)
515515
call assert_fails('lrewind', 'E924:')
516516

@@ -643,14 +643,14 @@ function XquickfixChangedByAutocmd(cchar)
643643
let Xgetexpr = a:cchar . 'getexpr'
644644
let Xrewind = a:cchar . 'rewind'
645645
if a:cchar == 'c'
646-
let Xsetlist = 'setqflist('
646+
let Xsetlist = function('setqflist')
647647
let ErrorNr = 'E925'
648648
function! ReadFunc()
649649
colder
650650
cgetexpr []
651651
endfunc
652652
else
653-
let Xsetlist = 'setloclist(0,'
653+
let Xsetlist = function('setloclist', [0])
654654
let ErrorNr = 'E926'
655655
function! ReadFunc()
656656
lolder
@@ -660,15 +660,15 @@ function XquickfixChangedByAutocmd(cchar)
660660

661661
augroup testgroup
662662
au!
663-
autocmd BufReadCmd t call ReadFunc()
663+
autocmd BufReadCmd test_changed.txt call ReadFunc()
664664
augroup END
665665

666-
bwipe!
666+
new | only
667667
let words = [ "a", "b" ]
668668
let qflist = []
669669
for word in words
670-
call add(qflist, {'filename': 't'})
671-
exec "call " . Xsetlist . "qflist, '')"
670+
call add(qflist, {'filename': 'test_changed.txt'})
671+
call Xsetlist(qflist, ' ')
672672
endfor
673673
exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')"
674674

@@ -745,3 +745,89 @@ function Test_setqflist()
745745

746746
call delete('Xtestfile')
747747
endfunction
748+
749+
function! XquickfixSetListWithAct(cchar)
750+
let Xolder = a:cchar . 'older'
751+
let Xnewer = a:cchar . 'newer'
752+
if a:cchar == 'c'
753+
let Xsetlist = function('setqflist')
754+
let Xgetlist = function('getqflist')
755+
else
756+
let Xsetlist = function('setloclist', [0])
757+
let Xgetlist = function('getloclist', [0])
758+
endif
759+
let list1 = [{'filename': 'fnameA', 'text': 'A'},
760+
\ {'filename': 'fnameB', 'text': 'B'}]
761+
let list2 = [{'filename': 'fnameC', 'text': 'C'},
762+
\ {'filename': 'fnameD', 'text': 'D'},
763+
\ {'filename': 'fnameE', 'text': 'E'}]
764+
765+
" {action} is unspecified. Same as specifing ' '.
766+
new | only
767+
exec "silent! " . Xnewer . "99"
768+
call Xsetlist(list1)
769+
call Xsetlist(list2)
770+
let li = Xgetlist()
771+
call assert_equal(3, len(li))
772+
call assert_equal('C', li[0]['text'])
773+
call assert_equal('D', li[1]['text'])
774+
call assert_equal('E', li[2]['text'])
775+
exec "silent! " . Xolder
776+
let li = Xgetlist()
777+
call assert_equal(2, len(li))
778+
call assert_equal('A', li[0]['text'])
779+
call assert_equal('B', li[1]['text'])
780+
781+
" {action} is specified ' '.
782+
new | only
783+
exec "silent! " . Xnewer . "99"
784+
call Xsetlist(list1)
785+
call Xsetlist(list2, ' ')
786+
let li = Xgetlist()
787+
call assert_equal(3, len(li))
788+
call assert_equal('C', li[0]['text'])
789+
call assert_equal('D', li[1]['text'])
790+
call assert_equal('E', li[2]['text'])
791+
exec "silent! " . Xolder
792+
let li = Xgetlist()
793+
call assert_equal(2, len(li))
794+
call assert_equal('A', li[0]['text'])
795+
call assert_equal('B', li[1]['text'])
796+
797+
" {action} is specified 'a'.
798+
new | only
799+
exec "silent! " . Xnewer . "99"
800+
call Xsetlist(list1)
801+
call Xsetlist(list2, 'a')
802+
let li = Xgetlist()
803+
call assert_equal(5, len(li))
804+
call assert_equal('A', li[0]['text'])
805+
call assert_equal('B', li[1]['text'])
806+
call assert_equal('C', li[2]['text'])
807+
call assert_equal('D', li[3]['text'])
808+
call assert_equal('E', li[4]['text'])
809+
810+
" {action} is specified 'r'.
811+
new | only
812+
exec "silent! " . Xnewer . "99"
813+
call Xsetlist(list1)
814+
call Xsetlist(list2, 'r')
815+
let li = Xgetlist()
816+
call assert_equal(3, len(li))
817+
call assert_equal('C', li[0]['text'])
818+
call assert_equal('D', li[1]['text'])
819+
call assert_equal('E', li[2]['text'])
820+
821+
" Test for wrong value.
822+
new | only
823+
call assert_fails("call Xsetlist(0)", 'E714:')
824+
call assert_fails("call Xsetlist(list1, '')", 'E927:')
825+
call assert_fails("call Xsetlist(list1, 'aa')", 'E927:')
826+
call assert_fails("call Xsetlist(list1, ' a')", 'E927:')
827+
call assert_fails("call Xsetlist(list1, 0)", 'E928:')
828+
endfunc
829+
830+
function Test_quickfix_set_list_with_act()
831+
call XquickfixSetListWithAct('c')
832+
call XquickfixSetListWithAct('l')
833+
endfunction

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,8 @@ static char *(features[]) =
748748

749749
static int included_patches[] =
750750
{ /* Add new patch number below this line */
751+
/**/
752+
1768,
751753
/**/
752754
1767,
753755
/**/

0 commit comments

Comments
 (0)