Mercurial > vim
comparison src/userfunc.c @ 31081:c12069d28719 v9.0.0875
patch 9.0.0875: using freed memory when executing delfunc at more prompt
Commit: https://github.com/vim/vim/commit/398a26f7fcd58fbc6e2329f892edbb7479a971bb
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Nov 13 22:13:33 2022 +0000
patch 9.0.0875: using freed memory when executing delfunc at more prompt
Problem: Using freed memory when executing delfunc at the more prompt.
Solution: Check function list not changed in another place. (closes https://github.com/vim/vim/issues/11437)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 13 Nov 2022 23:15:03 +0100 |
parents | 360f286b5869 |
children | 684e6dfa2fba |
comparison
equal
deleted
inserted
replaced
31080:df91dcf490f2 | 31081:c12069d28719 |
---|---|
3791 { | 3791 { |
3792 return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name; | 3792 return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name; |
3793 } | 3793 } |
3794 | 3794 |
3795 /* | 3795 /* |
3796 * When "prev_ht_changed" does not equal "ht_changed" give an error and return | |
3797 * TRUE. Otherwise return FALSE. | |
3798 */ | |
3799 static int | |
3800 function_list_modified(int prev_ht_changed) | |
3801 { | |
3802 if (prev_ht_changed != func_hashtab.ht_changed) | |
3803 { | |
3804 emsg(_(e_function_list_was_modified)); | |
3805 return TRUE; | |
3806 } | |
3807 return FALSE; | |
3808 } | |
3809 | |
3810 /* | |
3796 * List the head of the function: "function name(arg1, arg2)". | 3811 * List the head of the function: "function name(arg1, arg2)". |
3797 */ | 3812 */ |
3798 static void | 3813 static int |
3799 list_func_head(ufunc_T *fp, int indent) | 3814 list_func_head(ufunc_T *fp, int indent) |
3800 { | 3815 { |
3816 int prev_ht_changed = func_hashtab.ht_changed; | |
3801 int j; | 3817 int j; |
3802 | 3818 |
3803 msg_start(); | 3819 msg_start(); |
3820 | |
3821 // a timer at the more prompt may have deleted the function | |
3822 if (function_list_modified(prev_ht_changed)) | |
3823 return FAIL; | |
3824 | |
3804 if (indent) | 3825 if (indent) |
3805 msg_puts(" "); | 3826 msg_puts(" "); |
3806 if (fp->uf_def_status != UF_NOT_COMPILED) | 3827 if (fp->uf_def_status != UF_NOT_COMPILED) |
3807 msg_puts("def "); | 3828 msg_puts("def "); |
3808 else | 3829 else |
3875 if (fp->uf_flags & FC_CLOSURE) | 3896 if (fp->uf_flags & FC_CLOSURE) |
3876 msg_puts(" closure"); | 3897 msg_puts(" closure"); |
3877 msg_clr_eos(); | 3898 msg_clr_eos(); |
3878 if (p_verbose > 0) | 3899 if (p_verbose > 0) |
3879 last_set_msg(fp->uf_script_ctx); | 3900 last_set_msg(fp->uf_script_ctx); |
3901 | |
3902 return OK; | |
3880 } | 3903 } |
3881 | 3904 |
3882 /* | 3905 /* |
3883 * Get a function name, translating "<SID>" and "<SNR>". | 3906 * Get a function name, translating "<SID>" and "<SNR>". |
3884 * Also handles a Funcref in a List or Dictionary. | 3907 * Also handles a Funcref in a List or Dictionary. |
4313 * Otherwise functions matching "regmatch". | 4336 * Otherwise functions matching "regmatch". |
4314 */ | 4337 */ |
4315 void | 4338 void |
4316 list_functions(regmatch_T *regmatch) | 4339 list_functions(regmatch_T *regmatch) |
4317 { | 4340 { |
4318 int changed = func_hashtab.ht_changed; | 4341 int prev_ht_changed = func_hashtab.ht_changed; |
4319 long_u todo = func_hashtab.ht_used; | 4342 long_u todo = func_hashtab.ht_used; |
4320 hashitem_T *hi; | 4343 hashitem_T *hi; |
4321 | 4344 |
4322 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) | 4345 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) |
4323 { | 4346 { |
4331 ? !message_filtered(fp->uf_name) | 4354 ? !message_filtered(fp->uf_name) |
4332 && !func_name_refcount(fp->uf_name) | 4355 && !func_name_refcount(fp->uf_name) |
4333 : !isdigit(*fp->uf_name) | 4356 : !isdigit(*fp->uf_name) |
4334 && vim_regexec(regmatch, fp->uf_name, 0))) | 4357 && vim_regexec(regmatch, fp->uf_name, 0))) |
4335 { | 4358 { |
4336 list_func_head(fp, FALSE); | 4359 if (list_func_head(fp, FALSE) == FAIL) |
4337 if (changed != func_hashtab.ht_changed) | |
4338 { | |
4339 emsg(_(e_function_list_was_modified)); | |
4340 return; | 4360 return; |
4341 } | 4361 if (function_list_modified(prev_ht_changed)) |
4362 return; | |
4342 } | 4363 } |
4343 } | 4364 } |
4344 } | 4365 } |
4345 } | 4366 } |
4346 | 4367 |
4540 fp = find_func(up, FALSE); | 4561 fp = find_func(up, FALSE); |
4541 } | 4562 } |
4542 | 4563 |
4543 if (fp != NULL) | 4564 if (fp != NULL) |
4544 { | 4565 { |
4545 list_func_head(fp, TRUE); | 4566 // Check no function was added or removed from a timer, e.g. at |
4546 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j) | 4567 // the more prompt. "fp" may then be invalid. |
4568 int prev_ht_changed = func_hashtab.ht_changed; | |
4569 | |
4570 if (list_func_head(fp, TRUE) == OK) | |
4547 { | 4571 { |
4548 if (FUNCLINE(fp, j) == NULL) | 4572 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j) |
4549 continue; | 4573 { |
4550 msg_putchar('\n'); | 4574 if (FUNCLINE(fp, j) == NULL) |
4551 msg_outnum((long)(j + 1)); | 4575 continue; |
4552 if (j < 9) | 4576 msg_putchar('\n'); |
4553 msg_putchar(' '); | 4577 msg_outnum((long)(j + 1)); |
4554 if (j < 99) | 4578 if (j < 9) |
4555 msg_putchar(' '); | 4579 msg_putchar(' '); |
4556 msg_prt_line(FUNCLINE(fp, j), FALSE); | 4580 if (j < 99) |
4557 out_flush(); // show a line at a time | 4581 msg_putchar(' '); |
4558 ui_breakcheck(); | 4582 if (function_list_modified(prev_ht_changed)) |
4559 } | 4583 break; |
4560 if (!got_int) | 4584 msg_prt_line(FUNCLINE(fp, j), FALSE); |
4561 { | 4585 out_flush(); // show a line at a time |
4562 msg_putchar('\n'); | 4586 ui_breakcheck(); |
4563 if (fp->uf_def_status != UF_NOT_COMPILED) | 4587 } |
4564 msg_puts(" enddef"); | 4588 if (!got_int) |
4565 else | 4589 { |
4566 msg_puts(" endfunction"); | 4590 msg_putchar('\n'); |
4591 if (!function_list_modified(prev_ht_changed)) | |
4592 { | |
4593 if (fp->uf_def_status != UF_NOT_COMPILED) | |
4594 msg_puts(" enddef"); | |
4595 else | |
4596 msg_puts(" endfunction"); | |
4597 } | |
4598 } | |
4567 } | 4599 } |
4568 } | 4600 } |
4569 else | 4601 else |
4570 emsg_funcname(e_undefined_function_str, eap->arg); | 4602 emsg_funcname(e_undefined_function_str, eap->arg); |
4571 } | 4603 } |