diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-04-15 13:17:32 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-04-15 13:31:10 +0800 |
commit | 4b49f312a05214d5d1974f7ac2702ffb407fc558 (patch) | |
tree | f4f7515c461d2d599e60b043995843fa54062f3e | |
parent | 3d80392cab8ba41757769e18ffde9e8258365472 (diff) | |
download | rneovim-4b49f312a05214d5d1974f7ac2702ffb407fc558.tar.gz rneovim-4b49f312a05214d5d1974f7ac2702ffb407fc558.tar.bz2 rneovim-4b49f312a05214d5d1974f7ac2702ffb407fc558.zip |
vim-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 vim/vim#5976)
https://github.com/vim/vim/commit/9d8d0b5c644ea53364d04403740b3f23e57c1497
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | src/nvim/eval.c | 8 | ||||
-rw-r--r-- | test/old/testdir/test_eval_stuff.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_execute_func.vim | 2 | ||||
-rw-r--r-- | test/old/testdir/test_expr.vim | 23 | ||||
-rw-r--r-- | test/old/testdir/test_filter_map.vim | 6 | ||||
-rw-r--r-- | test/old/testdir/test_let.vim | 18 | ||||
-rw-r--r-- | test/old/testdir/test_listdict.vim | 1 | ||||
-rw-r--r-- | test/old/testdir/test_partial.vim | 45 |
8 files changed, 88 insertions, 17 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 6a8b24ceed..46cd837a73 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -789,6 +789,9 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv, int argc, typval_T *r } } else if (expr->v_type == VAR_PARTIAL) { partial_T *const partial = expr->vval.v_partial; + if (partial == NULL) { + return FAIL; + } const char *const s = partial_name(partial); if (s == NULL || *s == NUL) { return FAIL; @@ -8640,8 +8643,9 @@ int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, bool ic) } if ((typ1->v_type == VAR_PARTIAL && typ1->vval.v_partial == NULL) || (typ2->v_type == VAR_PARTIAL && typ2->vval.v_partial == NULL)) { - // when a partial is NULL assume not equal - n1 = false; + // When both partials are NULL, then they are equal. + // Otherwise they are not equal. + n1 = (typ1->vval.v_partial == typ2->vval.v_partial); } else if (type_is) { if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC) { // strings are considered the same if their value is diff --git a/test/old/testdir/test_eval_stuff.vim b/test/old/testdir/test_eval_stuff.vim index 1cf039342d..6a7fb223e0 100644 --- a/test/old/testdir/test_eval_stuff.vim +++ b/test/old/testdir/test_eval_stuff.vim @@ -205,7 +205,7 @@ func Test_vvar_scriptversion1() call assert_equal(511, 0o777) endfunc -func Test_excute_null() +func Test_execute_cmd_with_null() call assert_fails('execute v:_null_list', 'E730:') call assert_fails('execute v:_null_dict', 'E731:') call assert_fails('execute v:_null_blob', 'E976:') diff --git a/test/old/testdir/test_execute_func.vim b/test/old/testdir/test_execute_func.vim index 171cea1e49..cc294b7316 100644 --- a/test/old/testdir/test_execute_func.vim +++ b/test/old/testdir/test_execute_func.vim @@ -170,7 +170,7 @@ func Test_win_execute_visual_redraw() bwipe! endfunc -func Test_execute_null() +func Test_execute_cmd_with_null() call assert_equal("", execute(v:_null_string)) call assert_equal("", execute(v:_null_list)) call assert_fails('call execute(v:_null_dict)', 'E731:') diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim index 1810cf6741..b8ef87d714 100644 --- a/test/old/testdir/test_expr.vim +++ b/test/old/testdir/test_expr.vim @@ -22,6 +22,9 @@ func Test_equal() call assert_false([base.method] == [instance.other]) call assert_fails('echo base.method > instance.method') + " Nvim doesn't have null functions + " call assert_equal(0, test_null_function() == function('min')) + " call assert_equal(1, test_null_function() == test_null_function()) endfunc func Test_version() @@ -712,4 +715,24 @@ func Test_expr_eval_error() call assert_fails("let v = -{}", 'E728:') 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 diff --git a/test/old/testdir/test_filter_map.vim b/test/old/testdir/test_filter_map.vim index c75177ea39..e2216e4d68 100644 --- a/test/old/testdir/test_filter_map.vim +++ b/test/old/testdir/test_filter_map.vim @@ -93,6 +93,12 @@ func Test_map_filter_fails() call assert_equal(v:_null_dict, filter(v:_null_dict, 0)) call assert_equal(v:_null_list, map(v:_null_list, '"> " .. v:val')) call assert_equal(v:_null_dict, map(v:_null_dict, '"> " .. v:val')) + " Nvim doesn't have null functions + " call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_function())) + call assert_fails("let l = filter([1, 2], function('min'))", 'E118:') + " Nvim doesn't have null partials + " 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 func Test_map_and_modify() diff --git a/test/old/testdir/test_let.vim b/test/old/testdir/test_let.vim index fe7633cf11..6fbf305624 100644 --- a/test/old/testdir/test_let.vim +++ b/test/old/testdir/test_let.vim @@ -85,6 +85,24 @@ func Test_let() let l:Test_Local_Var = {'k' : 5} call assert_match("\nl:Test_Local_Var {'k': 5}", execute('let l:')) 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 func s:set_arg1(a) abort diff --git a/test/old/testdir/test_listdict.vim b/test/old/testdir/test_listdict.vim index a6a1c736c4..dc4abc3a7e 100644 --- a/test/old/testdir/test_listdict.vim +++ b/test/old/testdir/test_listdict.vim @@ -1081,6 +1081,7 @@ func Test_null_dict() call assert_equal('{}', string(d)) call assert_fails('let x = v:_null_dict[10]') call assert_equal({}, {}) + call assert_equal(0, len(copy(d))) endfunc " Test for the indexof() function diff --git a/test/old/testdir/test_partial.vim b/test/old/testdir/test_partial.vim index 3020668f1b..f813539d42 100644 --- a/test/old/testdir/test_partial.vim +++ b/test/old/testdir/test_partial.vim @@ -63,16 +63,18 @@ endfunc func Test_partial_dict() let dict = {'name': 'hello'} let Cb = function('MyDictFunc', ["foo", "bar"], dict) + call test_garbagecollect_now() call assert_equal("hello/foo/bar", Cb()) call assert_fails('Cb("xxx")', 'E492:') + let Cb = function('MyDictFunc', ["foo"], dict) + call assert_equal("hello/foo/xxx", Cb("xxx")) + call assert_fails('Cb()', 'E492:') + let Cb = function('MyDictFunc', [], dict) call assert_equal("hello/ttt/xxx", Cb("ttt", "xxx")) call assert_fails('Cb("yyy")', 'E492:') - let Cb = function('MyDictFunc', ["foo"], dict) - call assert_equal("hello/foo/xxx", Cb("xxx")) - call assert_fails('Cb()', 'E492:') let Cb = function('MyDictFunc', dict) call assert_equal("hello/xxx/yyy", Cb("xxx", "yyy")) call assert_fails('Cb("fff")', 'E492:') @@ -238,17 +240,22 @@ endfunc func Ignored(job1, job2, status) endfunc -" func Test_cycle_partial_job() -" let job = job_start('echo') -" call job_setoptions(job, {'exit_cb': function('Ignored', [job])}) -" unlet job -" endfunc +func Test_cycle_partial_job() + if has('job') + let job = job_start('echo') + call job_setoptions(job, {'exit_cb': function('Ignored', [job])}) + unlet job + endif +endfunc -" func Test_ref_job_partial_dict() -" let g:ref_job = job_start('echo') -" let d = {'a': 'b'} -" call job_setoptions(g:ref_job, {'exit_cb': function('string', [], d)}) -" endfunc +func Test_ref_job_partial_dict() + if has('job') + let g:ref_job = job_start('echo') + let d = {'a': 'b'} + call job_setoptions(g:ref_job, {'exit_cb': function('string', [], d)}) + call test_garbagecollect_now() + endif +endfunc func Test_auto_partial_rebind() let dict1 = {'name': 'dict1'} @@ -356,6 +363,18 @@ func Test_compare_partials() call assert_true(F1 isnot# F2) " Different functions call assert_true(F1 isnot# F1d1) " Partial /= non-partial call assert_true(d1.f1 isnot# d1.f1) " handle_subscript creates new partial each time + + " compare two null partials + " Nvim doesn't have null partials + " let N1 = test_null_partial() + let N1 = function('min') + 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 " vim: shiftwidth=2 sts=2 expandtab |