Mercurial > vim
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 |