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