To: vim_dev@googlegroups.com Subject: Patch 7.4.1768 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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) Files: src/eval.c, src/testdir/test_quickfix.vim *** ../vim-7.4.1767/src/eval.c 2016-04-21 08:56:07.022097293 +0200 --- src/eval.c 2016-04-21 19:28:49.935082045 +0200 *************** *** 98,103 **** --- 98,104 ---- 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,18287 **** typval_T *rettv) { #ifdef FEAT_QUICKFIX char_u *act; ! int action = ' '; #endif rettv->vval.v_number = -1; --- 18281,18289 ---- typval_T *rettv) { #ifdef FEAT_QUICKFIX + static char *e_invact = N_("E927: Invalid action: '%s'"); char_u *act; ! int action = 0; #endif rettv->vval.v_number = -1; *************** *** 18298,18308 **** act = get_tv_string_chk(action_arg); if (act == NULL) return; /* type error; errmsg already given */ ! if (*act == 'a' || *act == 'r') action = *act; } ! if (l != NULL && set_errorlist(wp, l, action, (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK) rettv->vval.v_number = 0; } --- 18300,18316 ---- act = get_tv_string_chk(action_arg); if (act == NULL) return; /* type error; errmsg already given */ ! if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) action = *act; + 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; } *** ../vim-7.4.1767/src/testdir/test_quickfix.vim 2016-04-18 20:03:54.103519308 +0200 --- src/testdir/test_quickfix.vim 2016-04-21 19:33:04.100406223 +0200 *************** *** 501,507 **** function Test_locationlist_curwin_was_closed() augroup testgroup au! ! autocmd BufReadCmd t call R(expand("")) augroup END function! R(n) --- 501,507 ---- function Test_locationlist_curwin_was_closed() augroup testgroup au! ! autocmd BufReadCmd test_curwin.txt call R(expand("")) augroup END function! R(n) *************** *** 510,516 **** new let q = [] ! call add(q, {'filename': 't' }) call setloclist(0, q) call assert_fails('lrewind', 'E924:') --- 510,516 ---- new let q = [] ! call add(q, {'filename': 'test_curwin.txt' }) call setloclist(0, q) call assert_fails('lrewind', 'E924:') *************** *** 643,656 **** let Xgetexpr = a:cchar . 'getexpr' let Xrewind = a:cchar . 'rewind' if a:cchar == 'c' ! let Xsetlist = 'setqflist(' let ErrorNr = 'E925' function! ReadFunc() colder cgetexpr [] endfunc else ! let Xsetlist = 'setloclist(0,' let ErrorNr = 'E926' function! ReadFunc() lolder --- 643,656 ---- let Xgetexpr = a:cchar . 'getexpr' let Xrewind = a:cchar . 'rewind' if a:cchar == 'c' ! let Xsetlist = function('setqflist') let ErrorNr = 'E925' function! ReadFunc() colder cgetexpr [] endfunc else ! let Xsetlist = function('setloclist', [0]) let ErrorNr = 'E926' function! ReadFunc() lolder *************** *** 660,674 **** augroup testgroup au! ! autocmd BufReadCmd t call ReadFunc() augroup END ! bwipe! let words = [ "a", "b" ] let qflist = [] for word in words ! call add(qflist, {'filename': 't'}) ! exec "call " . Xsetlist . "qflist, '')" endfor exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')" --- 660,674 ---- augroup testgroup au! ! autocmd BufReadCmd test_changed.txt call ReadFunc() augroup END ! new | only let words = [ "a", "b" ] let qflist = [] for word in words ! call add(qflist, {'filename': 'test_changed.txt'}) ! call Xsetlist(qflist, ' ') endfor exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')" *************** *** 745,747 **** --- 745,833 ---- 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 *** ../vim-7.4.1767/src/version.c 2016-04-21 18:20:03.662235811 +0200 --- src/version.c 2016-04-21 19:32:13.160942225 +0200 *************** *** 750,751 **** --- 750,753 ---- { /* Add new patch number below this line */ + /**/ + 1768, /**/ -- WOMAN: I didn't know we had a king. I thought we were an autonomous collective. DENNIS: You're fooling yourself. We're living in a dictatorship. A self-perpetuating autocracy in which the working classes-- WOMAN: Oh there you go, bringing class into it again. DENNIS: That's what it's all about if only people would-- The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///