comparison src/vim9compile.c @ 23285:112fa621b127 v8.2.2188

patch 8.2.2188: Vim9: crash when calling global function from :def function Commit: https://github.com/vim/vim/commit/cd45ed03bfdd7fac53d562ad402df74bd26e7754 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Dec 22 17:35:54 2020 +0100 patch 8.2.2188: Vim9: crash when calling global function from :def function Problem: Vim9: crash when calling global function from :def function. Solution: Set the outer context. Define the partial for the context on the original function. Use a refcount to keep track of which ufunc is using a dfunc. (closes #7525)
author Bram Moolenaar <Bram@vim.org>
date Tue, 22 Dec 2020 17:45:03 +0100
parents 00f7cd9b6033
children ac701146c708
comparison
equal deleted inserted replaced
23284:3d54c7fa353c 23285:112fa621b127
7334 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len; 7334 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
7335 CLEAR_POINTER(dfunc); 7335 CLEAR_POINTER(dfunc);
7336 dfunc->df_idx = def_functions.ga_len; 7336 dfunc->df_idx = def_functions.ga_len;
7337 ufunc->uf_dfunc_idx = dfunc->df_idx; 7337 ufunc->uf_dfunc_idx = dfunc->df_idx;
7338 dfunc->df_ufunc = ufunc; 7338 dfunc->df_ufunc = ufunc;
7339 dfunc->df_name = vim_strsave(ufunc->uf_name);
7340 ++dfunc->df_refcount;
7339 ++def_functions.ga_len; 7341 ++def_functions.ga_len;
7340 return OK; 7342 return OK;
7341 } 7343 }
7342 7344
7343 /* 7345 /*
7926 + ufunc->uf_dfunc_idx; 7928 + ufunc->uf_dfunc_idx;
7927 7929
7928 for (idx = 0; idx < instr->ga_len; ++idx) 7930 for (idx = 0; idx < instr->ga_len; ++idx)
7929 delete_instr(((isn_T *)instr->ga_data) + idx); 7931 delete_instr(((isn_T *)instr->ga_data) + idx);
7930 ga_clear(instr); 7932 ga_clear(instr);
7933 VIM_CLEAR(dfunc->df_name);
7931 7934
7932 // If using the last entry in the table and it was added above, we 7935 // If using the last entry in the table and it was added above, we
7933 // might as well remove it. 7936 // might as well remove it.
7934 if (!dfunc->df_deleted && new_def_function 7937 if (!dfunc->df_deleted && new_def_function
7935 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1) 7938 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
8100 char_u *lambda = isn->isn_arg.newfunc.nf_lambda; 8103 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
8101 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL); 8104 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
8102 8105
8103 if (ufunc != NULL) 8106 if (ufunc != NULL)
8104 { 8107 {
8105 // Clear uf_dfunc_idx so that the function is deleted. 8108 unlink_def_function(ufunc);
8106 clear_def_function(ufunc);
8107 ufunc->uf_dfunc_idx = 0;
8108 func_ptr_unref(ufunc); 8109 func_ptr_unref(ufunc);
8109 } 8110 }
8110 8111
8111 vim_free(lambda); 8112 vim_free(lambda);
8112 vim_free(isn->isn_arg.newfunc.nf_global); 8113 vim_free(isn->isn_arg.newfunc.nf_global);
8204 break; 8205 break;
8205 } 8206 }
8206 } 8207 }
8207 8208
8208 /* 8209 /*
8209 * Free all instructions for "dfunc". 8210 * Free all instructions for "dfunc" except df_name.
8210 */ 8211 */
8211 static void 8212 static void
8212 delete_def_function_contents(dfunc_T *dfunc) 8213 delete_def_function_contents(dfunc_T *dfunc)
8213 { 8214 {
8214 int idx; 8215 int idx;
8225 dfunc->df_deleted = TRUE; 8226 dfunc->df_deleted = TRUE;
8226 } 8227 }
8227 8228
8228 /* 8229 /*
8229 * When a user function is deleted, clear the contents of any associated def 8230 * When a user function is deleted, clear the contents of any associated def
8230 * function. The position in def_functions can be re-used. 8231 * function, unless another user function still uses it.
8232 * The position in def_functions can be re-used.
8231 */ 8233 */
8232 void 8234 void
8233 clear_def_function(ufunc_T *ufunc) 8235 unlink_def_function(ufunc_T *ufunc)
8234 { 8236 {
8235 if (ufunc->uf_dfunc_idx > 0) 8237 if (ufunc->uf_dfunc_idx > 0)
8236 { 8238 {
8237 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 8239 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8238 + ufunc->uf_dfunc_idx; 8240 + ufunc->uf_dfunc_idx;
8239 8241
8240 delete_def_function_contents(dfunc); 8242 if (--dfunc->df_refcount <= 0)
8243 delete_def_function_contents(dfunc);
8241 ufunc->uf_def_status = UF_NOT_COMPILED; 8244 ufunc->uf_def_status = UF_NOT_COMPILED;
8242 } 8245 ufunc->uf_dfunc_idx = 0;
8243 } 8246 if (dfunc->df_ufunc == ufunc)
8244 8247 dfunc->df_ufunc = NULL;
8245 /* 8248 }
8246 * Used when a user function is about to be deleted: remove the pointer to it. 8249 }
8247 * The entry in def_functions is then unused. 8250
8251 /*
8252 * Used when a user function refers to an existing dfunc.
8248 */ 8253 */
8249 void 8254 void
8250 unlink_def_function(ufunc_T *ufunc) 8255 link_def_function(ufunc_T *ufunc)
8251 { 8256 {
8252 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; 8257 if (ufunc->uf_dfunc_idx > 0)
8253 8258 {
8254 dfunc->df_ufunc = NULL; 8259 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8260 + ufunc->uf_dfunc_idx;
8261
8262 ++dfunc->df_refcount;
8263 }
8255 } 8264 }
8256 8265
8257 #if defined(EXITFREE) || defined(PROTO) 8266 #if defined(EXITFREE) || defined(PROTO)
8258 /* 8267 /*
8259 * Free all functions defined with ":def". 8268 * Free all functions defined with ":def".
8266 for (idx = 0; idx < def_functions.ga_len; ++idx) 8275 for (idx = 0; idx < def_functions.ga_len; ++idx)
8267 { 8276 {
8268 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx; 8277 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
8269 8278
8270 delete_def_function_contents(dfunc); 8279 delete_def_function_contents(dfunc);
8280 vim_free(dfunc->df_name);
8271 } 8281 }
8272 8282
8273 ga_clear(&def_functions); 8283 ga_clear(&def_functions);
8274 } 8284 }
8275 #endif 8285 #endif