mirror of
https://github.com/neovim/neovim.git
synced 2024-12-29 14:41:06 -07:00
vim-patch:8.2.3756: might crash when callback is not valid
Problem: might crash when callback is not valid.
Solution: Check for valid callback. (Yegappan Lakshmanan, closes vim/vim#9293)
4dc24eb5ad
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
parent
42e44d6d33
commit
d7bd7f13a8
@ -5860,6 +5860,7 @@ bool callback_from_typval(Callback *const callback, typval_T *const arg)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return whether the callback could be called.
|
||||||
bool callback_call(Callback *const callback, const int argcount_in, typval_T *const argvars_in,
|
bool callback_call(Callback *const callback, const int argcount_in, typval_T *const argvars_in,
|
||||||
typval_T *const rettv)
|
typval_T *const rettv)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
@ -8705,9 +8706,9 @@ bool invoke_prompt_interrupt(void)
|
|||||||
argv[0].v_type = VAR_UNKNOWN;
|
argv[0].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
got_int = false; // don't skip executing commands
|
got_int = false; // don't skip executing commands
|
||||||
callback_call(&curbuf->b_prompt_interrupt, 0, argv, &rettv);
|
int ret = callback_call(&curbuf->b_prompt_interrupt, 0, argv, &rettv);
|
||||||
tv_clear(&rettv);
|
tv_clear(&rettv);
|
||||||
return true;
|
return ret != FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare "typ1" and "typ2". Put the result in "typ1".
|
/// Compare "typ1" and "typ2". Put the result in "typ1".
|
||||||
|
@ -1394,7 +1394,7 @@ func_call_skip_call:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// call the 'callback' function and return the result as a number.
|
/// call the 'callback' function and return the result as a number.
|
||||||
/// Returns -1 when calling the function fails. Uses argv[0] to argv[argc - 1]
|
/// Returns -2 when calling the function fails. Uses argv[0] to argv[argc - 1]
|
||||||
/// for the function arguments. argv[argc] should have type VAR_UNKNOWN.
|
/// for the function arguments. argv[argc] should have type VAR_UNKNOWN.
|
||||||
///
|
///
|
||||||
/// @param argcount number of "argvars"
|
/// @param argcount number of "argvars"
|
||||||
@ -1403,7 +1403,7 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv
|
|||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
if (!callback_call(callback, argcount, argvars, &rettv)) {
|
if (!callback_call(callback, argcount, argvars, &rettv)) {
|
||||||
return -1;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
varnumber_T retval = tv_get_number_chk(&rettv, NULL);
|
varnumber_T retval = tv_get_number_chk(&rettv, NULL);
|
||||||
|
@ -2233,7 +2233,7 @@ static Callback tsrfu_cb; ///< 'thesaurusfunc' callback function
|
|||||||
static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb)
|
static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb)
|
||||||
{
|
{
|
||||||
callback_free(bufcb);
|
callback_free(bufcb);
|
||||||
if (globcb->data.funcref != NULL && *globcb->data.funcref != NUL) {
|
if (globcb->type != kCallbackNone) {
|
||||||
callback_copy(bufcb, globcb);
|
callback_copy(bufcb, globcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2290,11 +2290,9 @@ int set_thesaurusfunc_option(void)
|
|||||||
|
|
||||||
if (*curbuf->b_p_tsrfu != NUL) {
|
if (*curbuf->b_p_tsrfu != NUL) {
|
||||||
// buffer-local option set
|
// buffer-local option set
|
||||||
callback_free(&curbuf->b_tsrfu_cb);
|
|
||||||
retval = option_set_callback_func(curbuf->b_p_tsrfu, &curbuf->b_tsrfu_cb);
|
retval = option_set_callback_func(curbuf->b_p_tsrfu, &curbuf->b_tsrfu_cb);
|
||||||
} else {
|
} else {
|
||||||
// global option set
|
// global option set
|
||||||
callback_free(&tsrfu_cb);
|
|
||||||
retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
|
retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5193,7 +5193,7 @@ int option_set_callback_func(char *optval, Callback *optcb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Callback cb;
|
Callback cb;
|
||||||
if (!callback_from_typval(&cb, tv)) {
|
if (!callback_from_typval(&cb, tv) || cb.type == kCallbackNone) {
|
||||||
tv_free(tv);
|
tv_free(tv);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ void free_tagfunc_option(void)
|
|||||||
void set_buflocal_tfu_callback(buf_T *buf)
|
void set_buflocal_tfu_callback(buf_T *buf)
|
||||||
{
|
{
|
||||||
callback_free(&buf->b_tfu_cb);
|
callback_free(&buf->b_tfu_cb);
|
||||||
if (tfu_cb.data.funcref != NULL && *tfu_cb.data.funcref != NUL) {
|
if (tfu_cb.type != kCallbackNone) {
|
||||||
callback_copy(&buf->b_tfu_cb, &tfu_cb);
|
callback_copy(&buf->b_tfu_cb, &tfu_cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1153,7 +1153,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*curbuf->b_p_tfu == NUL) {
|
if (*curbuf->b_p_tfu == NUL || curbuf->b_tfu_cb.type == kCallbackNone) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1491,6 +1491,15 @@ func Test_completefunc_callback()
|
|||||||
" call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
|
" call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
|
||||||
" call assert_equal([], g:MycompleteFunc2_args)
|
" call assert_equal([], g:MycompleteFunc2_args)
|
||||||
|
|
||||||
|
" set 'completefunc' to a non-existing function
|
||||||
|
set completefunc=MycompleteFunc2
|
||||||
|
call setline(1, 'five')
|
||||||
|
call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
|
||||||
|
call assert_fails("let &completefunc = function('NonExistingFunc')", 'E700:')
|
||||||
|
let g:MycompleteFunc2_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'five']], g:MycompleteFunc2_args)
|
||||||
|
|
||||||
" cleanup
|
" cleanup
|
||||||
delfunc MycompleteFunc1
|
delfunc MycompleteFunc1
|
||||||
delfunc MycompleteFunc2
|
delfunc MycompleteFunc2
|
||||||
@ -1702,6 +1711,15 @@ func Test_omnifunc_callback()
|
|||||||
" call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
|
" call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
|
||||||
" call assert_equal([], g:MyomniFunc2_args)
|
" call assert_equal([], g:MyomniFunc2_args)
|
||||||
|
|
||||||
|
" set 'omnifunc' to a non-existing function
|
||||||
|
set omnifunc=MyomniFunc2
|
||||||
|
call setline(1, 'nine')
|
||||||
|
call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
|
||||||
|
call assert_fails("let &omnifunc = function('NonExistingFunc')", 'E700:')
|
||||||
|
let g:MyomniFunc2_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'nine']], g:MyomniFunc2_args)
|
||||||
|
|
||||||
" cleanup
|
" cleanup
|
||||||
delfunc MyomniFunc1
|
delfunc MyomniFunc1
|
||||||
delfunc MyomniFunc2
|
delfunc MyomniFunc2
|
||||||
@ -1939,6 +1957,16 @@ func Test_thesaurusfunc_callback()
|
|||||||
call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
|
||||||
call assert_equal('sunday', getline(1))
|
call assert_equal('sunday', getline(1))
|
||||||
call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
|
call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
|
||||||
|
%bw!
|
||||||
|
|
||||||
|
" set 'thesaurusfunc' to a non-existing function
|
||||||
|
set thesaurusfunc=MytsrFunc2
|
||||||
|
call setline(1, 'ten')
|
||||||
|
call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:')
|
||||||
|
call assert_fails("let &thesaurusfunc = function('NonExistingFunc')", 'E700:')
|
||||||
|
let g:MytsrFunc2_args = []
|
||||||
|
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
|
||||||
|
call assert_equal([[1, ''], [0, 'ten']], g:MytsrFunc2_args)
|
||||||
|
|
||||||
" cleanup
|
" cleanup
|
||||||
set thesaurusfunc&
|
set thesaurusfunc&
|
||||||
|
@ -315,6 +315,11 @@ func Test_tagfunc_callback()
|
|||||||
" call assert_fails("tag a17", "E117:")
|
" call assert_fails("tag a17", "E117:")
|
||||||
" call assert_equal([], g:MytagFunc3_args)
|
" call assert_equal([], g:MytagFunc3_args)
|
||||||
|
|
||||||
|
" set 'tagfunc' to a non-existing function
|
||||||
|
call assert_fails("set tagfunc=function('NonExistingFunc')", 'E700:')
|
||||||
|
call assert_fails("let &tagfunc = function('NonExistingFunc')", 'E700:')
|
||||||
|
call assert_fails("tag axb123", 'E426:')
|
||||||
|
|
||||||
" cleanup
|
" cleanup
|
||||||
delfunc MytagFunc1
|
delfunc MytagFunc1
|
||||||
delfunc MytagFunc2
|
delfunc MytagFunc2
|
||||||
|
Loading…
Reference in New Issue
Block a user