comparison src/vim9execute.c @ 27591:d91be28bbdbb v8.2.4322

patch 8.2.4322: Vim9: crash when using funcref with closure Commit: https://github.com/vim/vim/commit/7aca5ca6763e50d2c23953b20e30fca7457c9abf Author: Bram Moolenaar <Bram@vim.org> Date: Mon Feb 7 19:56:43 2022 +0000 patch 8.2.4322: Vim9: crash when using funcref with closure Problem: Vim9: crash when using funcref with closure. Solution: Keep a reference to the funcref that has the outer context. (closes #9716)
author Bram Moolenaar <Bram@vim.org>
date Mon, 07 Feb 2022 21:00:02 +0100
parents a31dd0a3cb39
children a6ffe874a24b
comparison
equal deleted inserted replaced
27590:cc44ec730954 27591:d91be28bbdbb
230 static void 230 static void
231 dict_stack_clear(int len) 231 dict_stack_clear(int len)
232 { 232 {
233 while (dict_stack.ga_len > len) 233 while (dict_stack.ga_len > len)
234 dict_stack_drop(); 234 dict_stack_drop();
235 }
236
237 /*
238 * Get a pointer to useful "pt_outer" of "pt".
239 */
240 static outer_T *
241 get_pt_outer(partial_T *pt)
242 {
243 partial_T *ptref = pt->pt_outer_partial;
244
245 if (ptref == NULL)
246 return &pt->pt_outer;
247
248 // partial using partial (recursively)
249 while (ptref->pt_outer_partial != NULL)
250 ptref = ptref->pt_outer_partial;
251 return &ptref->pt_outer;
235 } 252 }
236 253
237 /* 254 /*
238 * Call compiled function "cdf_idx" from compiled code. 255 * Call compiled function "cdf_idx" from compiled code.
239 * This adds a stack frame and sets the instruction pointer to the start of the 256 * This adds a stack frame and sets the instruction pointer to the start of the
419 436
420 if (ref == NULL) 437 if (ref == NULL)
421 return FAIL; 438 return FAIL;
422 if (pt != NULL) 439 if (pt != NULL)
423 { 440 {
424 ref->or_outer = &pt->pt_outer; 441 ref->or_outer = get_pt_outer(pt);
425 ++pt->pt_refcount; 442 ++pt->pt_refcount;
426 ref->or_partial = pt; 443 ref->or_partial = pt;
427 } 444 }
428 else if (ufunc->uf_partial != NULL) 445 else if (ufunc->uf_partial != NULL)
429 { 446 {
430 ref->or_outer = &ufunc->uf_partial->pt_outer; 447 ref->or_outer = get_pt_outer(ufunc->uf_partial);
431 ++ufunc->uf_partial->pt_refcount; 448 ++ufunc->uf_partial->pt_refcount;
432 ref->or_partial = ufunc->uf_partial; 449 ref->or_partial = ufunc->uf_partial;
433 } 450 }
434 else 451 else
435 { 452 {
5084 ectx.ec_outer_ref = ALLOC_CLEAR_ONE(outer_ref_T); 5101 ectx.ec_outer_ref = ALLOC_CLEAR_ONE(outer_ref_T);
5085 if (ectx.ec_outer_ref == NULL) 5102 if (ectx.ec_outer_ref == NULL)
5086 goto failed_early; 5103 goto failed_early;
5087 if (partial != NULL) 5104 if (partial != NULL)
5088 { 5105 {
5089 if (partial->pt_outer.out_stack == NULL) 5106 outer_T *outer = get_pt_outer(partial);
5107
5108 if (outer->out_stack == NULL)
5090 { 5109 {
5091 if (current_ectx != NULL) 5110 if (current_ectx != NULL)
5092 { 5111 {
5093 if (current_ectx->ec_outer_ref != NULL 5112 if (current_ectx->ec_outer_ref != NULL
5094 && current_ectx->ec_outer_ref->or_outer != NULL) 5113 && current_ectx->ec_outer_ref->or_outer != NULL)
5097 } 5116 }
5098 // Should there be an error here? 5117 // Should there be an error here?
5099 } 5118 }
5100 else 5119 else
5101 { 5120 {
5102 ectx.ec_outer_ref->or_outer = &partial->pt_outer; 5121 ectx.ec_outer_ref->or_outer = outer;
5103 ++partial->pt_refcount; 5122 ++partial->pt_refcount;
5104 ectx.ec_outer_ref->or_partial = partial; 5123 ectx.ec_outer_ref->or_partial = partial;
5105 } 5124 }
5106 } 5125 }
5107 else 5126 else