neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 8156eece24134dc26b927d44cd860e44f81cd61c
parent b058a801e7515dd09154f60d7de0219f92635fb8
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Mon,  1 Dec 2025 13:45:00 +0800

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

Diffstat:
Msrc/nvim/eval/userfunc.c | 38+++++++++++++++++++++++++++-----------
Msrc/nvim/eval/vars.c | 18+++++++++---------
2 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c @@ -3906,41 +3906,57 @@ funccall_T *get_funccal(void) return funccal; } -/// @return hashtable used for local variables in the current funccal or +/// @return dict used for local variables in the current funccal or /// NULL if there is no current funccal. -hashtab_T *get_funccal_local_ht(void) +dict_T *get_funccal_local_dict(void) { - if (current_funccal == NULL) { + if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) { return NULL; } - return &get_funccal()->fc_l_vars.dv_hashtab; + return &get_funccal()->fc_l_vars; +} + +/// @return hashtable used for local variables in the current funccal or +/// NULL if there is no current funccal. +hashtab_T *get_funccal_local_ht(void) +{ + dict_T *d = get_funccal_local_dict(); + return d != NULL ? &d->dv_hashtab : NULL; } /// @return the l: scope variable or /// NULL if there is no current funccal. 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 (dictitem_T *)&get_funccal()->fc_l_vars_var; } -/// @return the hashtable used for argument in the current funccal or +/// @return the dict used for argument in the current funccal or /// NULL if there is no current funccal. -hashtab_T *get_funccal_args_ht(void) +dict_T *get_funccal_args_dict(void) { - if (current_funccal == NULL) { + if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 0) { return NULL; } - return &get_funccal()->fc_l_avars.dv_hashtab; + return &get_funccal()->fc_l_avars; +} + +/// @return the hashtable used for argument in the current funccal or +/// NULL if there is no current funccal. +hashtab_T *get_funccal_args_ht(void) +{ + dict_T *d = get_funccal_args_dict(); + return d != NULL ? &d->dv_hashtab : NULL; } /// @return the a: scope variable or /// NULL if there is no current funccal. 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 (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. 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, first); } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c @@ -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, dict_T **d) { - funccall_T *funccal = get_funccal(); *d = NULL; 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; } - if (funccal == NULL) { // global variable - *d = get_globvar_dict(); - } else { // l: variable - *d = &funccal->fc_l_vars; + *d = get_funccal_local_dict(); + if (*d != NULL) { // local variable + goto end; } + + *d = get_globvar_dict(); // global variable 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; } else if (*name == 'v') { // v: variable *d = get_vimvar_dict(); - } else if (*name == 'a' && funccal != NULL) { // function argument - *d = &funccal->fc_l_avars; - } else if (*name == 'l' && funccal != NULL) { // local variable - *d = &funccal->fc_l_vars; + } else if (*name == 'a') { // a: function argument + *d = get_funccal_args_dict(); + } else if (*name == 'l') { // l: local variable + *d = get_funccal_local_dict(); } else if (*name == 's' // script variable && (current_sctx.sc_sid > 0 || current_sctx.sc_sid == SID_STR || current_sctx.sc_sid == SID_LUA)