mirror of
https://github.com/neovim/neovim.git
synced 2026-09-03 21:00:34 +00:00
vim-patch:9.2.0996: debugger: crash when evaluating a variable in a :def function frame (#41460)
Problem: In the debugger ">up" and ">frame" select an older function call
frame, but get_funccal_local_ht() and the related functions check
current_funccal while returning a dictionary of the frame that
get_funccal() selected. A :def function keeps its local variables
on the vim9 stack, its funccall_T has no l: and a: dictionaries and
is allocated cleared, so with such a frame selected the returned
hashtab has a NULL ht_array and evaluating any variable name at the
debug prompt crashes in hash_lookup().
Solution: Check the funccal that is actually used and return NULL when it has
no l: variables, so that the variable is reported as undefined
instead.
closes: vim/vim#21111
5ad47b07af
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3944,14 +3944,29 @@ funccall_T *get_funccal(void)
|
||||
return funccal;
|
||||
}
|
||||
|
||||
/// Get the function call environment to use for the l: and a: variables, based
|
||||
/// on the backtrace debug level.
|
||||
/// Returns NULL if there is no current funccal.
|
||||
static funccall_T *get_funccal_for_vars(void)
|
||||
{
|
||||
funccall_T *funccal = NULL;
|
||||
|
||||
if (current_funccal == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
funccal = get_funccal();
|
||||
if (funccal == NULL || funccal->fc_l_vars.dv_refcount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return funccal;
|
||||
}
|
||||
|
||||
/// @return dict used for local variables in the current funccal or
|
||||
/// NULL if there is no current funccal.
|
||||
dict_T *get_funccal_local_dict(void)
|
||||
{
|
||||
if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return &get_funccal()->fc_l_vars;
|
||||
funccall_T *funccal = get_funccal_for_vars();
|
||||
return funccal == NULL ? NULL : &funccal->fc_l_vars;
|
||||
}
|
||||
|
||||
/// @return hashtable used for local variables in the current funccal or
|
||||
@@ -3966,20 +3981,16 @@ hashtab_T *get_funccal_local_ht(void)
|
||||
/// NULL if there is no current funccal.
|
||||
dictitem_T *get_funccal_local_var(void)
|
||||
{
|
||||
if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return (dictitem_T *)&get_funccal()->fc_l_vars_var;
|
||||
funccall_T *funccal = get_funccal_for_vars();
|
||||
return funccal == NULL ? NULL : (dictitem_T *)&funccal->fc_l_vars_var;
|
||||
}
|
||||
|
||||
/// @return the dict used for argument in the current funccal or
|
||||
/// NULL if there is no current funccal.
|
||||
dict_T *get_funccal_args_dict(void)
|
||||
{
|
||||
if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return &get_funccal()->fc_l_avars;
|
||||
funccall_T *funccal = get_funccal_for_vars();
|
||||
return funccal == NULL ? NULL : &funccal->fc_l_avars;
|
||||
}
|
||||
|
||||
/// @return the hashtable used for argument in the current funccal or
|
||||
@@ -3994,10 +4005,8 @@ hashtab_T *get_funccal_args_ht(void)
|
||||
/// NULL if there is no current funccal.
|
||||
dictitem_T *get_funccal_args_var(void)
|
||||
{
|
||||
if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return (dictitem_T *)&get_funccal()->fc_l_avars_var;
|
||||
funccall_T *funccal = get_funccal_for_vars();
|
||||
return funccal == NULL ? NULL : (dictitem_T *)&funccal->fc_l_avars_var;
|
||||
}
|
||||
|
||||
/// List function variables, if there is a function.
|
||||
|
||||
Reference in New Issue
Block a user