changeset 8965:90f7dc794aa0 v7.4.1768

commit https://github.com/vim/vim/commit/d106e5ba7f10f0d2a14eaefe5d78405044416cb9 Author: Bram Moolenaar <Bram@vim.org> 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)
author Christian Brabandt <cb@256bit.org>
date Thu, 21 Apr 2016 19:45:06 +0200
parents f487d0cb64ea
children 2aff38480967
files src/eval.c src/testdir/test_quickfix.vim src/version.c
diffstat 3 files changed, 109 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- 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;
     }
--- 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("<amatch>"))
+      autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
     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
--- 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,