# HG changeset patch # User Christian Brabandt # Date 1461260706 -7200 # Node ID 90f7dc794aa0c6ec03e6876e13079a171dc95e4f # Parent f487d0cb64ea78931541b767fe9ab5206d7ff9c1 commit https://github.com/vim/vim/commit/d106e5ba7f10f0d2a14eaefe5d78405044416cb9 Author: Bram Moolenaar Date: Thu Apr 21 19:38:07 2016 +0200 patch 7.4.1768 Problem: Arguments of setqflist() are not checked properly. Solution: Add better checks, add a test. (Nikolai Pavlov, Hirohito Higashi, closes https://github.com/vim/vim/issues/661) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -98,6 +98,7 @@ static char *e_listarg = N_("E686: Argum static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary"); static char *e_listreq = N_("E714: List required"); static char *e_dictreq = N_("E715: Dictionary required"); +static char *e_stringreq = N_("E928: String required"); static char *e_toomanyarg = N_("E118: Too many arguments for function: %s"); static char *e_dictkey = N_("E716: Key not present in Dictionary: %s"); static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); @@ -18280,8 +18281,9 @@ set_qf_ll_list( typval_T *rettv) { #ifdef FEAT_QUICKFIX + static char *e_invact = N_("E927: Invalid action: '%s'"); char_u *act; - int action = ' '; + int action = 0; #endif rettv->vval.v_number = -1; @@ -18298,11 +18300,17 @@ set_qf_ll_list( act = get_tv_string_chk(action_arg); if (act == NULL) return; /* type error; errmsg already given */ - if (*act == 'a' || *act == 'r') + if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) action = *act; - } - - if (l != NULL && set_errorlist(wp, l, action, + else + EMSG2(_(e_invact), act); + } + else if (action_arg->v_type == VAR_UNKNOWN) + action = ' '; + else + EMSG(_(e_stringreq)); + + if (l != NULL && action && set_errorlist(wp, l, action, (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK) rettv->vval.v_number = 0; } 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 @@ -501,7 +501,7 @@ endfunction function Test_locationlist_curwin_was_closed() augroup testgroup au! - autocmd BufReadCmd t call R(expand("")) + autocmd BufReadCmd test_curwin.txt call R(expand("")) augroup END function! R(n) @@ -510,7 +510,7 @@ function Test_locationlist_curwin_was_cl new let q = [] - call add(q, {'filename': 't' }) + call add(q, {'filename': 'test_curwin.txt' }) call setloclist(0, q) call assert_fails('lrewind', 'E924:') @@ -643,14 +643,14 @@ function XquickfixChangedByAutocmd(cchar let Xgetexpr = a:cchar . 'getexpr' let Xrewind = a:cchar . 'rewind' if a:cchar == 'c' - let Xsetlist = 'setqflist(' + let Xsetlist = function('setqflist') let ErrorNr = 'E925' function! ReadFunc() colder cgetexpr [] endfunc else - let Xsetlist = 'setloclist(0,' + let Xsetlist = function('setloclist', [0]) let ErrorNr = 'E926' function! ReadFunc() lolder @@ -660,15 +660,15 @@ function XquickfixChangedByAutocmd(cchar augroup testgroup au! - autocmd BufReadCmd t call ReadFunc() + autocmd BufReadCmd test_changed.txt call ReadFunc() augroup END - bwipe! + new | only let words = [ "a", "b" ] let qflist = [] for word in words - call add(qflist, {'filename': 't'}) - exec "call " . Xsetlist . "qflist, '')" + call add(qflist, {'filename': 'test_changed.txt'}) + call Xsetlist(qflist, ' ') endfor exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')" @@ -745,3 +745,89 @@ function Test_setqflist() call delete('Xtestfile') endfunction + +function! XquickfixSetListWithAct(cchar) + let Xolder = a:cchar . 'older' + let Xnewer = a:cchar . 'newer' + if a:cchar == 'c' + let Xsetlist = function('setqflist') + let Xgetlist = function('getqflist') + else + let Xsetlist = function('setloclist', [0]) + let Xgetlist = function('getloclist', [0]) + endif + let list1 = [{'filename': 'fnameA', 'text': 'A'}, + \ {'filename': 'fnameB', 'text': 'B'}] + let list2 = [{'filename': 'fnameC', 'text': 'C'}, + \ {'filename': 'fnameD', 'text': 'D'}, + \ {'filename': 'fnameE', 'text': 'E'}] + + " {action} is unspecified. Same as specifing ' '. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2) + let li = Xgetlist() + call assert_equal(3, len(li)) + call assert_equal('C', li[0]['text']) + call assert_equal('D', li[1]['text']) + call assert_equal('E', li[2]['text']) + exec "silent! " . Xolder + let li = Xgetlist() + call assert_equal(2, len(li)) + call assert_equal('A', li[0]['text']) + call assert_equal('B', li[1]['text']) + + " {action} is specified ' '. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2, ' ') + let li = Xgetlist() + call assert_equal(3, len(li)) + call assert_equal('C', li[0]['text']) + call assert_equal('D', li[1]['text']) + call assert_equal('E', li[2]['text']) + exec "silent! " . Xolder + let li = Xgetlist() + call assert_equal(2, len(li)) + call assert_equal('A', li[0]['text']) + call assert_equal('B', li[1]['text']) + + " {action} is specified 'a'. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2, 'a') + let li = Xgetlist() + call assert_equal(5, len(li)) + call assert_equal('A', li[0]['text']) + call assert_equal('B', li[1]['text']) + call assert_equal('C', li[2]['text']) + call assert_equal('D', li[3]['text']) + call assert_equal('E', li[4]['text']) + + " {action} is specified 'r'. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2, 'r') + let li = Xgetlist() + call assert_equal(3, len(li)) + call assert_equal('C', li[0]['text']) + call assert_equal('D', li[1]['text']) + call assert_equal('E', li[2]['text']) + + " Test for wrong value. + new | only + call assert_fails("call Xsetlist(0)", 'E714:') + call assert_fails("call Xsetlist(list1, '')", 'E927:') + call assert_fails("call Xsetlist(list1, 'aa')", 'E927:') + call assert_fails("call Xsetlist(list1, ' a')", 'E927:') + call assert_fails("call Xsetlist(list1, 0)", 'E928:') +endfunc + +function Test_quickfix_set_list_with_act() + call XquickfixSetListWithAct('c') + call XquickfixSetListWithAct('l') +endfunction diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -749,6 +749,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1768, +/**/ 1767, /**/ 1766,