comparison src/vim9execute.c @ 32274:83caf07aedd6 v9.0.1468

patch 9.0.1468: recursively calling :defer function if it does :qa Commit: https://github.com/vim/vim/commit/a1f2b5ddc63d4e2b6ab047d8c839dd8477b36aba Author: zeertzjq <zeertzjq@outlook.com> Date: Tue Apr 18 21:04:53 2023 +0100 patch 9.0.1468: recursively calling :defer function if it does :qa Problem: Recursively calling :defer function if it does :qa in a compiled function. Solution: Clear the defer entry before calling the function. (closes #12271)
author Bram Moolenaar <Bram@vim.org>
date Tue, 18 Apr 2023 22:15:04 +0200
parents 012facc8e25c
children 2e07c2bb2f60
comparison
equal deleted inserted replaced
32273:a7e63171cbfb 32274:83caf07aedd6
1061 listitem_T *arg_li = l->lv_first; 1061 listitem_T *arg_li = l->lv_first;
1062 typval_T *functv = &l->lv_first->li_tv; 1062 typval_T *functv = &l->lv_first->li_tv;
1063 int obj_off = functv->v_type == VAR_PARTIAL ? 1 : 0; 1063 int obj_off = functv->v_type == VAR_PARTIAL ? 1 : 0;
1064 int argcount = l->lv_len - 1 - obj_off; 1064 int argcount = l->lv_len - 1 - obj_off;
1065 1065
1066 if (functv->vval.v_string == NULL)
1067 // already being called, can happen if function does ":qa"
1068 continue;
1069
1066 if (obj_off == 1) 1070 if (obj_off == 1)
1067 arg_li = arg_li->li_next; // second list item is the object 1071 arg_li = arg_li->li_next; // second list item is the object
1068 for (i = 0; i < argcount; ++i) 1072 for (i = 0; i < argcount; ++i)
1069 { 1073 {
1070 arg_li = arg_li->li_next; 1074 arg_li = arg_li->li_next;
1080 funcexe.fe_partial = functv->vval.v_partial; 1084 funcexe.fe_partial = functv->vval.v_partial;
1081 funcexe.fe_object = l->lv_first->li_next->li_tv.vval.v_object; 1085 funcexe.fe_object = l->lv_first->li_next->li_tv.vval.v_object;
1082 if (funcexe.fe_object != NULL) 1086 if (funcexe.fe_object != NULL)
1083 ++funcexe.fe_object->obj_refcount; 1087 ++funcexe.fe_object->obj_refcount;
1084 } 1088 }
1085 (void)call_func(functv->vval.v_string, -1, 1089
1086 &rettv, argcount, argvars, &funcexe); 1090 char_u *name = functv->vval.v_string;
1091 functv->vval.v_string = NULL;
1092
1093 (void)call_func(name, -1, &rettv, argcount, argvars, &funcexe);
1094
1087 clear_tv(&rettv); 1095 clear_tv(&rettv);
1096 vim_free(name);
1088 } 1097 }
1089 } 1098 }
1090 1099
1091 /* 1100 /*
1092 * Return from the current function. 1101 * Return from the current function.