0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.2.0633: crash when using null partial in filter()

Problem:    Crash when using null partial in filter().
Solution:   Fix crash.  Add more tests. (Yegappan Lakshmanan, closes #5976)
This commit is contained in:
Bram Moolenaar
2020-04-24 22:47:31 +02:00
parent 92c461ef1b
commit 9d8d0b5c64
14 changed files with 114 additions and 4 deletions

View File

@@ -241,6 +241,9 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
{ {
partial_T *partial = expr->vval.v_partial; partial_T *partial = expr->vval.v_partial;
if (partial == NULL)
return FAIL;
if (partial->pt_func != NULL && partial->pt_func->uf_dfunc_idx >= 0) if (partial->pt_func != NULL && partial->pt_func->uf_dfunc_idx >= 0)
{ {
if (call_def_function(partial->pt_func, argc, argv, rettv) == FAIL) if (call_def_function(partial->pt_func, argc, argv, rettv) == FAIL)
@@ -6416,8 +6419,9 @@ typval_compare(
&& typ1->vval.v_partial == NULL) && typ1->vval.v_partial == NULL)
|| (typ2->v_type == VAR_PARTIAL || (typ2->v_type == VAR_PARTIAL
&& typ2->vval.v_partial == NULL)) && typ2->vval.v_partial == NULL))
// when a partial is NULL assume not equal // When both partials are NULL, then they are equal.
n1 = FALSE; // Otherwise they are not equal.
n1 = (typ1->vval.v_partial == typ2->vval.v_partial);
else if (type_is) else if (type_is)
{ {
if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC) if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC)

View File

@@ -142,6 +142,7 @@ func Test_blob_compare()
let b2 = b1[:] let b2 = b1[:]
call assert_true(b1 == b2) call assert_true(b1 == b2)
call assert_false(b1 is b2) call assert_false(b1 is b2)
call assert_true(b1 isnot b2)
call assert_fails('let x = b1 > b2') call assert_fails('let x = b1 > b2')
call assert_fails('let x = b1 < b2') call assert_fails('let x = b1 < b2')

View File

@@ -1203,6 +1203,7 @@ func Test_out_cb()
\ 'err_cb': dict.errHandler, \ 'err_cb': dict.errHandler,
\ 'err_mode': 'json'}) \ 'err_mode': 'json'})
call assert_equal("run", job_status(job)) call assert_equal("run", job_status(job))
call test_garbagecollect_now()
try try
let g:Ch_outmsg = '' let g:Ch_outmsg = ''
let g:Ch_errmsg = '' let g:Ch_errmsg = ''
@@ -1818,6 +1819,7 @@ func Test_read_nonl_in_close_cb()
let g:out = '' let g:out = ''
let arg = 'import sys;sys.stdout.write("1\n2\n3")' let arg = 'import sys;sys.stdout.write("1\n2\n3")'
call job_start([s:python, '-c', arg], {'close_cb': function('s:close_cb')}) call job_start([s:python, '-c', arg], {'close_cb': function('s:close_cb')})
call test_garbagecollect_now()
call WaitForAssert({-> assert_equal('123', g:out)}) call WaitForAssert({-> assert_equal('123', g:out)})
unlet g:out unlet g:out
delfunc s:close_cb delfunc s:close_cb
@@ -1828,6 +1830,7 @@ func Test_read_from_terminated_job()
let arg = 'import os,sys;os.close(1);sys.stderr.write("test\n")' let arg = 'import os,sys;os.close(1);sys.stderr.write("test\n")'
call job_start([s:python, '-c', arg], {'callback': {-> execute('let g:linecount += 1')}}) call job_start([s:python, '-c', arg], {'callback': {-> execute('let g:linecount += 1')}})
call WaitForAssert({-> assert_equal(1, g:linecount)}) call WaitForAssert({-> assert_equal(1, g:linecount)})
call test_garbagecollect_now()
unlet g:linecount unlet g:linecount
endfunc endfunc

View File

@@ -217,7 +217,7 @@ func Test_scriptversion_fail()
call delete('Xversionscript') call delete('Xversionscript')
endfunc endfunc
func Test_excute_null() func Test_execute_cmd_with_null()
call assert_fails('execute test_null_list()', 'E730:') call assert_fails('execute test_null_list()', 'E730:')
call assert_fails('execute test_null_dict()', 'E731:') call assert_fails('execute test_null_dict()', 'E731:')
call assert_fails('execute test_null_blob()', 'E976:') call assert_fails('execute test_null_blob()', 'E976:')

View File

@@ -132,7 +132,7 @@ func Test_win_execute_other_tab()
unlet xyz unlet xyz
endfunc endfunc
func Test_execute_null() func Test_execute_func_with_null()
call assert_equal("", execute(test_null_string())) call assert_equal("", execute(test_null_string()))
call assert_equal("", execute(test_null_list())) call assert_equal("", execute(test_null_list()))
call assert_fails('call execute(test_null_dict())', 'E731:') call assert_fails('call execute(test_null_dict())', 'E731:')
@@ -143,3 +143,5 @@ func Test_execute_null()
call assert_fails('call execute(test_null_channel())', 'E908:') call assert_fails('call execute(test_null_channel())', 'E908:')
endif endif
endfunc endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -1,5 +1,7 @@
" Tests for expressions. " Tests for expressions.
source check.vim
func Test_equal() func Test_equal()
let base = {} let base = {}
func base.method() func base.method()
@@ -20,6 +22,8 @@ func Test_equal()
call assert_false([base.method] == [instance.other]) call assert_false([base.method] == [instance.other])
call assert_fails('echo base.method > instance.method') call assert_fails('echo base.method > instance.method')
call assert_equal(0, test_null_function() == function('min'))
call assert_equal(1, test_null_function() == test_null_function())
endfunc endfunc
func Test_version() func Test_version()
@@ -583,4 +587,24 @@ func Test_expr_eval_error()
call assert_fails("let v = -{}", 'E728:') call assert_fails("let v = -{}", 'E728:')
endfunc endfunc
" Test for float value comparison
func Test_float_compare()
CheckFeature float
call assert_true(1.2 == 1.2)
call assert_true(1.0 != 1.2)
call assert_true(1.2 > 1.0)
call assert_true(1.2 >= 1.2)
call assert_true(1.0 < 1.2)
call assert_true(1.2 <= 1.2)
call assert_true(+0.0 == -0.0)
" two NaNs (not a number) are not equal
call assert_true(sqrt(-4.01) != (0.0 / 0.0))
" two inf (infinity) are equal
call assert_true((1.0 / 0) == (2.0 / 0))
" two -inf (infinity) are equal
call assert_true(-(1.0 / 0) == -(2.0 / 0))
" +infinity != -infinity
call assert_true((1.0 / 0) != -(2.0 / 0))
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -99,6 +99,10 @@ func Test_map_filter_fails()
call assert_fails("let l = filter([1, 2], {})", 'E731:') call assert_fails("let l = filter([1, 2], {})", 'E731:')
call assert_equal(0, map(test_null_list(), '"> " .. v:val')) call assert_equal(0, map(test_null_list(), '"> " .. v:val'))
call assert_equal(0, map(test_null_dict(), '"> " .. v:val')) call assert_equal(0, map(test_null_dict(), '"> " .. v:val'))
call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_function()))
call assert_fails("let l = filter([1, 2], function('min'))", 'E118:')
call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_partial()))
call assert_fails("let l = filter([1, 2], {a, b, c -> 1})", 'E119:')
endfunc endfunc
func Test_map_and_modify() func Test_map_and_modify()

View File

@@ -794,3 +794,28 @@ func Test_fold_delete_first_line()
bwipe! bwipe!
set foldmethod& set foldmethod&
endfunc endfunc
" Test for errors in 'foldexpr'
func Test_fold_expr_error()
new
call setline(1, ['one', 'two', 'three'])
" Return a list from the expression
set foldexpr=[]
set foldmethod=expr
for i in range(3)
call assert_equal(0, foldlevel(i))
endfor
" expression error
set foldexpr=[{]
set foldmethod=expr
for i in range(3)
call assert_equal(0, foldlevel(i))
endfor
set foldmethod& foldexpr&
close!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -1239,6 +1239,8 @@ func Test_col()
call assert_equal(0, col([2, '$'])) call assert_equal(0, col([2, '$']))
call assert_equal(0, col([1, 100])) call assert_equal(0, col([1, 100]))
call assert_equal(0, col([1])) call assert_equal(0, col([1]))
call assert_equal(0, col(test_null_list()))
call assert_fails('let c = col({})', 'E731:')
" test for getting the visual start column " test for getting the visual start column
func T() func T()

View File

@@ -81,6 +81,24 @@ func Test_let()
let l:Test_Local_Var = {'k' : 5} let l:Test_Local_Var = {'k' : 5}
call assert_match("\nl:Test_Local_Var {'k': 5}", execute('let l:')) call assert_match("\nl:Test_Local_Var {'k': 5}", execute('let l:'))
call assert_match("v:errors []", execute('let v:')) call assert_match("v:errors []", execute('let v:'))
" Test for assigning multiple list items
let l = [1, 2, 3]
let [l[0], l[1]] = [10, 20]
call assert_equal([10, 20, 3], l)
" Test for errors in conditional expression
call assert_fails('let val = [] ? 1 : 2', 'E745:')
call assert_fails('let val = 1 ? 5+ : 6', 'E121:')
call assert_fails('let val = 1 ? 0 : 5+', 'E15:')
call assert_false(exists('val'))
" Test for errors in logical operators
let @a = 'if [] || 0 | let val = 2 | endif'
call assert_fails('exe @a', 'E745:')
call assert_fails('call feedkeys(":let val = 0 || []\<cr>", "xt")', 'E745:')
call assert_fails('exe "let val = [] && 5"', 'E745:')
call assert_fails('exe "let val = 6 && []"', 'E745:')
endfunc endfunc
func s:set_arg1(a) abort func s:set_arg1(a) abort
@@ -282,13 +300,20 @@ func Test_let_errors()
let d = {'k' : 4} let d = {'k' : 4}
call assert_fails('let d.# = 5', 'E713:') call assert_fails('let d.# = 5', 'E713:')
call assert_fails('let d.m += 5', 'E734:') call assert_fails('let d.m += 5', 'E734:')
call assert_fails('let m = d[{]', 'E15:')
let l = [1, 2] let l = [1, 2]
call assert_fails('let l[2] = 0', 'E684:') call assert_fails('let l[2] = 0', 'E684:')
call assert_fails('let l[0:1] = [1, 2, 3]', 'E710:') call assert_fails('let l[0:1] = [1, 2, 3]', 'E710:')
call assert_fails('let l[-2:-3] = [3, 4]', 'E684:') call assert_fails('let l[-2:-3] = [3, 4]', 'E684:')
call assert_fails('let l[0:4] = [5, 6]', 'E711:') call assert_fails('let l[0:4] = [5, 6]', 'E711:')
call assert_fails('let l -= 2', 'E734:')
call assert_fails('let l += 2', 'E734:')
call assert_fails('let g:["a;b"] = 10', 'E461:') call assert_fails('let g:["a;b"] = 10', 'E461:')
call assert_fails('let g:.min = function("max")', 'E704:') call assert_fails('let g:.min = function("max")', 'E704:')
if has('channel')
let ch = test_null_channel()
call assert_fails('let ch += 1', 'E734:')
endif
" This test works only when the language is English " This test works only when the language is English
if v:lang == "C" || v:lang =~ '^[Ee]n' if v:lang == "C" || v:lang =~ '^[Ee]n'

View File

@@ -943,6 +943,7 @@ func Test_null_list()
call assert_equal(0, uniq(l)) call assert_equal(0, uniq(l))
call assert_fails("let k = [] + l", 'E15:') call assert_fails("let k = [] + l", 'E15:')
call assert_fails("let k = l + []", 'E15:') call assert_fails("let k = l + []", 'E15:')
call assert_equal(0, len(copy(test_null_list())))
endfunc endfunc
" Test for a null dict " Test for a null dict
@@ -959,6 +960,7 @@ func Test_null_dict()
call assert_equal('{}', string(d)) call assert_equal('{}', string(d))
call assert_fails('let x = test_null_dict()[10]') call assert_fails('let x = test_null_dict()[10]')
call assert_equal({}, {}) call assert_equal({}, {})
call assert_equal(0, len(copy(test_null_dict())))
endfunc endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -63,6 +63,7 @@ endfunc
func Test_partial_dict() func Test_partial_dict()
let dict = {'name': 'hello'} let dict = {'name': 'hello'}
let Cb = function('MyDictFunc', ["foo", "bar"], dict) let Cb = function('MyDictFunc', ["foo", "bar"], dict)
call test_garbagecollect_now()
call assert_equal("hello/foo/bar", Cb()) call assert_equal("hello/foo/bar", Cb())
call assert_fails('Cb("xxx")', 'E492:') call assert_fails('Cb("xxx")', 'E492:')
@@ -282,6 +283,7 @@ func Test_ref_job_partial_dict()
let g:ref_job = job_start('echo') let g:ref_job = job_start('echo')
let d = {'a': 'b'} let d = {'a': 'b'}
call job_setoptions(g:ref_job, {'exit_cb': function('Ignored2', [], d)}) call job_setoptions(g:ref_job, {'exit_cb': function('Ignored2', [], d)})
call test_garbagecollect_now()
endif endif
endfunc endfunc
@@ -391,6 +393,16 @@ func Test_compare_partials()
call assert_true(F1 isnot# F2) " Different functions call assert_true(F1 isnot# F2) " Different functions
call assert_true(F1 isnot# F1d1) " Partial /= non-partial call assert_true(F1 isnot# F1d1) " Partial /= non-partial
call assert_true(d1.f1 isnot# d1.f1) " handle_subscript creates new partial each time call assert_true(d1.f1 isnot# d1.f1) " handle_subscript creates new partial each time
" compare two null partials
let N1 = test_null_partial()
let N2 = N1
call assert_true(N1 is N2)
call assert_true(N1 == N2)
" compare a partial and a null partial
call assert_false(N1 == F1)
call assert_false(F1 is N1)
endfunc endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -364,6 +364,10 @@ func Test_CmdCompletion()
com! -complete=custom, DoCmd com! -complete=custom, DoCmd
call assert_beeps("call feedkeys(':DoCmd \t', 'tx')") call assert_beeps("call feedkeys(':DoCmd \t', 'tx')")
" custom completion failure with the wrong function
com! -complete=custom,min DoCmd
call assert_fails("call feedkeys(':DoCmd \t', 'tx')", 'E118:')
delcom DoCmd delcom DoCmd
endfunc endfunc

View File

@@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
633,
/**/ /**/
632, 632,
/**/ /**/