fix(eval): fix crash with :breakadd expr when calling user func

This commit is contained in:
zeertzjq
2025-12-01 13:45:00 +08:00
parent b058a801e7
commit 8156eece24
2 changed files with 36 additions and 20 deletions

View File

@@ -3906,41 +3906,57 @@ funccall_T *get_funccal(void)
return funccal; 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;
}
/// @return hashtable used for local variables in the current funccal or /// @return hashtable used for local variables in the current funccal or
/// NULL if there is no current funccal. /// NULL if there is no current funccal.
hashtab_T *get_funccal_local_ht(void) hashtab_T *get_funccal_local_ht(void)
{ {
if (current_funccal == NULL) { dict_T *d = get_funccal_local_dict();
return NULL; return d != NULL ? &d->dv_hashtab : NULL;
}
return &get_funccal()->fc_l_vars.dv_hashtab;
} }
/// @return the l: scope variable or /// @return the l: scope variable or
/// NULL if there is no current funccal. /// NULL if there is no current funccal.
dictitem_T *get_funccal_local_var(void) dictitem_T *get_funccal_local_var(void)
{ {
if (current_funccal == NULL) { if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) {
return NULL; return NULL;
} }
return (dictitem_T *)&get_funccal()->fc_l_vars_var; return (dictitem_T *)&get_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;
}
/// @return the hashtable used for argument in the current funccal or /// @return the hashtable used for argument in the current funccal or
/// NULL if there is no current funccal. /// NULL if there is no current funccal.
hashtab_T *get_funccal_args_ht(void) hashtab_T *get_funccal_args_ht(void)
{ {
if (current_funccal == NULL) { dict_T *d = get_funccal_args_dict();
return NULL; return d != NULL ? &d->dv_hashtab : NULL;
}
return &get_funccal()->fc_l_avars.dv_hashtab;
} }
/// @return the a: scope variable or /// @return the a: scope variable or
/// NULL if there is no current funccal. /// NULL if there is no current funccal.
dictitem_T *get_funccal_args_var(void) dictitem_T *get_funccal_args_var(void)
{ {
if (current_funccal == NULL) { if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) {
return NULL; return NULL;
} }
return (dictitem_T *)&get_funccal()->fc_l_avars_var; return (dictitem_T *)&get_funccal()->fc_l_avars_var;
@@ -3949,7 +3965,7 @@ dictitem_T *get_funccal_args_var(void)
/// List function variables, if there is a function. /// List function variables, if there is a function.
void list_func_vars(int *first) void list_func_vars(int *first)
{ {
if (current_funccal != NULL) { if (current_funccal != NULL && current_funccal->fc_l_vars.dv_refcount > 0) {
list_hashtable_vars(&current_funccal->fc_l_vars.dv_hashtab, "l:", false, list_hashtable_vars(&current_funccal->fc_l_vars.dv_hashtab, "l:", false,
first); first);
} }

View File

@@ -2483,7 +2483,6 @@ dictitem_T *find_var_in_ht(hashtab_T *const ht, int htname, const char *const va
static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char **varname, static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char **varname,
dict_T **d) dict_T **d)
{ {
funccall_T *funccal = get_funccal();
*d = NULL; *d = NULL;
if (name_len == 0) { if (name_len == 0) {
@@ -2503,11 +2502,12 @@ static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, cons
return &compat_hashtab; return &compat_hashtab;
} }
if (funccal == NULL) { // global variable *d = get_funccal_local_dict();
*d = get_globvar_dict(); if (*d != NULL) { // local variable
} else { // l: variable goto end;
*d = &funccal->fc_l_vars;
} }
*d = get_globvar_dict(); // global variable
goto end; goto end;
} }
@@ -2529,10 +2529,10 @@ static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, cons
*d = curtab->tp_vars; *d = curtab->tp_vars;
} else if (*name == 'v') { // v: variable } else if (*name == 'v') { // v: variable
*d = get_vimvar_dict(); *d = get_vimvar_dict();
} else if (*name == 'a' && funccal != NULL) { // function argument } else if (*name == 'a') { // a: function argument
*d = &funccal->fc_l_avars; *d = get_funccal_args_dict();
} else if (*name == 'l' && funccal != NULL) { // local variable } else if (*name == 'l') { // l: local variable
*d = &funccal->fc_l_vars; *d = get_funccal_local_dict();
} else if (*name == 's' // script variable } else if (*name == 's' // script variable
&& (current_sctx.sc_sid > 0 || current_sctx.sc_sid == SID_STR && (current_sctx.sc_sid > 0 || current_sctx.sc_sid == SID_STR
|| current_sctx.sc_sid == SID_LUA) || current_sctx.sc_sid == SID_LUA)