Mercurial > vim
comparison src/userfunc.c @ 26566:ba52a5ef59f1 v8.2.3812
patch 8.2.3812: Vim9: leaking memory in numbered function test
Commit: https://github.com/vim/vim/commit/57bc2333b1d713bc54f8e33ef3ef7ac169af2ac4
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Dec 15 12:06:43 2021 +0000
patch 8.2.3812: Vim9: leaking memory in numbered function test
Problem: Vim9: leaking memory in numbered function test.
Solution: Skip "g:" when checking for numbered function. Clean up after
errors properly.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 15 Dec 2021 13:15:03 +0100 |
parents | dff04b7fa6b2 |
children | 5f4198087073 |
comparison
equal
deleted
inserted
replaced
26565:7e742336d4bd | 26566:ba52a5ef59f1 |
---|---|
2134 } | 2134 } |
2135 } | 2135 } |
2136 } | 2136 } |
2137 | 2137 |
2138 /* | 2138 /* |
2139 * Return TRUE if "name" is a numbered function, ignoring a "g:" prefix. | |
2140 */ | |
2141 static int | |
2142 numbered_function(char_u *name) | |
2143 { | |
2144 return isdigit(*name) | |
2145 || (name[0] == 'g' && name[1] == ':' && isdigit(name[2])); | |
2146 } | |
2147 | |
2148 /* | |
2139 * There are two kinds of function names: | 2149 * There are two kinds of function names: |
2140 * 1. ordinary names, function defined with :function or :def | 2150 * 1. ordinary names, function defined with :function or :def |
2141 * 2. numbered functions and lambdas | 2151 * 2. numbered functions and lambdas |
2142 * For the first we only count the name stored in func_hashtab as a reference, | 2152 * For the first we only count the name stored in func_hashtab as a reference, |
2143 * using function() does not count as a reference, because the function is | 2153 * using function() does not count as a reference, because the function is |
2144 * looked up by name. | 2154 * looked up by name. |
2145 */ | 2155 */ |
2146 int | 2156 int |
2147 func_name_refcount(char_u *name) | 2157 func_name_refcount(char_u *name) |
2148 { | 2158 { |
2149 return isdigit(*name) || *name == '<'; | 2159 return numbered_function(name) || *name == '<'; |
2150 } | 2160 } |
2151 | 2161 |
2152 /* | 2162 /* |
2153 * Unreference "fc": decrement the reference count and free it when it | 2163 * Unreference "fc": decrement the reference count and free it when it |
2154 * becomes zero. "fp" is detached from "fc". | 2164 * becomes zero. "fp" is detached from "fc". |
3954 garray_T newlines; | 3964 garray_T newlines; |
3955 int varargs = FALSE; | 3965 int varargs = FALSE; |
3956 int flags = 0; | 3966 int flags = 0; |
3957 char_u *ret_type = NULL; | 3967 char_u *ret_type = NULL; |
3958 ufunc_T *fp = NULL; | 3968 ufunc_T *fp = NULL; |
3969 int fp_allocated = FALSE; | |
3970 int free_fp = FALSE; | |
3959 int overwrite = FALSE; | 3971 int overwrite = FALSE; |
3960 dictitem_T *v; | 3972 dictitem_T *v; |
3961 funcdict_T fudi; | 3973 funcdict_T fudi; |
3962 static int func_nr = 0; // number for nameless function | 3974 static int func_nr = 0; // number for nameless function |
3963 int paren; | 3975 int paren; |
4458 } | 4470 } |
4459 | 4471 |
4460 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); | 4472 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); |
4461 if (fp == NULL) | 4473 if (fp == NULL) |
4462 goto erret; | 4474 goto erret; |
4475 fp_allocated = TRUE; | |
4463 | 4476 |
4464 if (fudi.fd_dict != NULL) | 4477 if (fudi.fd_dict != NULL) |
4465 { | 4478 { |
4466 if (fudi.fd_di == NULL) | 4479 if (fudi.fd_di == NULL) |
4467 { | 4480 { |
4488 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name); | 4501 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name); |
4489 | 4502 |
4490 // behave like "dict" was used | 4503 // behave like "dict" was used |
4491 flags |= FC_DICT; | 4504 flags |= FC_DICT; |
4492 } | 4505 } |
4493 | |
4494 // insert the new function in the function list | |
4495 set_ufunc_name(fp, name); | |
4496 if (overwrite) | |
4497 { | |
4498 hi = hash_find(&func_hashtab, name); | |
4499 hi->hi_key = UF2HIKEY(fp); | |
4500 } | |
4501 else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) | |
4502 { | |
4503 vim_free(fp); | |
4504 fp = NULL; | |
4505 goto erret; | |
4506 } | |
4507 fp->uf_refcount = 1; | |
4508 } | 4506 } |
4509 fp->uf_args = newargs; | 4507 fp->uf_args = newargs; |
4510 fp->uf_def_args = default_args; | 4508 fp->uf_def_args = default_args; |
4511 fp->uf_ret_type = &t_any; | 4509 fp->uf_ret_type = &t_any; |
4512 fp->uf_func_type = &t_func_any; | 4510 fp->uf_func_type = &t_func_any; |
4525 function_using_block_scopes(fp, cstack); | 4523 function_using_block_scopes(fp, cstack); |
4526 | 4524 |
4527 if (parse_argument_types(fp, &argtypes, varargs) == FAIL) | 4525 if (parse_argument_types(fp, &argtypes, varargs) == FAIL) |
4528 { | 4526 { |
4529 SOURCING_LNUM = lnum_save; | 4527 SOURCING_LNUM = lnum_save; |
4530 goto errret_2; | 4528 free_fp = fp_allocated; |
4529 goto erret; | |
4531 } | 4530 } |
4532 varargs = FALSE; | 4531 varargs = FALSE; |
4533 | 4532 |
4534 // parse the return type, if any | 4533 // parse the return type, if any |
4535 if (parse_return_type(fp, ret_type) == FAIL) | 4534 if (parse_return_type(fp, ret_type) == FAIL) |
4536 { | 4535 { |
4537 SOURCING_LNUM = lnum_save; | 4536 SOURCING_LNUM = lnum_save; |
4537 free_fp = fp_allocated; | |
4538 goto erret; | 4538 goto erret; |
4539 } | 4539 } |
4540 SOURCING_LNUM = lnum_save; | 4540 SOURCING_LNUM = lnum_save; |
4541 } | 4541 } |
4542 else | 4542 else |
4543 fp->uf_def_status = UF_NOT_COMPILED; | 4543 fp->uf_def_status = UF_NOT_COMPILED; |
4544 | 4544 |
4545 if (fp_allocated) | |
4546 { | |
4547 // insert the new function in the function list | |
4548 set_ufunc_name(fp, name); | |
4549 if (overwrite) | |
4550 { | |
4551 hi = hash_find(&func_hashtab, name); | |
4552 hi->hi_key = UF2HIKEY(fp); | |
4553 } | |
4554 else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) | |
4555 { | |
4556 free_fp = TRUE; | |
4557 goto erret; | |
4558 } | |
4559 fp->uf_refcount = 1; | |
4560 } | |
4561 | |
4545 fp->uf_lines = newlines; | 4562 fp->uf_lines = newlines; |
4563 newlines.ga_data = NULL; | |
4546 if ((flags & FC_CLOSURE) != 0) | 4564 if ((flags & FC_CLOSURE) != 0) |
4547 { | 4565 { |
4548 if (register_closure(fp) == FAIL) | 4566 if (register_closure(fp) == FAIL) |
4549 goto erret; | 4567 goto erret; |
4550 } | 4568 } |
4591 } | 4609 } |
4592 errret_2: | 4610 errret_2: |
4593 ga_clear_strings(&newlines); | 4611 ga_clear_strings(&newlines); |
4594 if (fp != NULL) | 4612 if (fp != NULL) |
4595 VIM_CLEAR(fp->uf_arg_types); | 4613 VIM_CLEAR(fp->uf_arg_types); |
4614 if (free_fp) | |
4615 { | |
4616 vim_free(fp); | |
4617 fp = NULL; | |
4618 } | |
4596 ret_free: | 4619 ret_free: |
4597 ga_clear_strings(&argtypes); | 4620 ga_clear_strings(&argtypes); |
4598 vim_free(line_to_free); | 4621 vim_free(line_to_free); |
4599 vim_free(fudi.fd_newkey); | 4622 vim_free(fudi.fd_newkey); |
4600 if (name != name_arg) | 4623 if (name != name_arg) |
4811 } | 4834 } |
4812 set_nextcmd(eap, p); | 4835 set_nextcmd(eap, p); |
4813 if (eap->nextcmd != NULL) | 4836 if (eap->nextcmd != NULL) |
4814 *p = NUL; | 4837 *p = NUL; |
4815 | 4838 |
4816 if (isdigit(*name) && fudi.fd_dict == NULL) | 4839 if (numbered_function(name) && fudi.fd_dict == NULL) |
4817 { | 4840 { |
4818 if (!eap->skip) | 4841 if (!eap->skip) |
4819 semsg(_(e_invarg2), eap->arg); | 4842 semsg(_(e_invarg2), eap->arg); |
4820 vim_free(name); | 4843 vim_free(name); |
4821 return; | 4844 return; |
4879 ufunc_T *fp = NULL; | 4902 ufunc_T *fp = NULL; |
4880 | 4903 |
4881 if (name == NULL || !func_name_refcount(name)) | 4904 if (name == NULL || !func_name_refcount(name)) |
4882 return; | 4905 return; |
4883 fp = find_func(name, FALSE, NULL); | 4906 fp = find_func(name, FALSE, NULL); |
4884 if (fp == NULL && isdigit(*name)) | 4907 if (fp == NULL && numbered_function(name)) |
4885 { | 4908 { |
4886 #ifdef EXITFREE | 4909 #ifdef EXITFREE |
4887 if (!entered_free_all_mem) | 4910 if (!entered_free_all_mem) |
4888 #endif | 4911 #endif |
4889 internal_error("func_unref()"); | 4912 internal_error("func_unref()"); |
4922 if (name == NULL || !func_name_refcount(name)) | 4945 if (name == NULL || !func_name_refcount(name)) |
4923 return; | 4946 return; |
4924 fp = find_func(name, FALSE, NULL); | 4947 fp = find_func(name, FALSE, NULL); |
4925 if (fp != NULL) | 4948 if (fp != NULL) |
4926 ++fp->uf_refcount; | 4949 ++fp->uf_refcount; |
4927 else if (isdigit(*name)) | 4950 else if (numbered_function(name)) |
4928 // Only give an error for a numbered function. | 4951 // Only give an error for a numbered function. |
4929 // Fail silently, when named or lambda function isn't found. | 4952 // Fail silently, when named or lambda function isn't found. |
4930 internal_error("func_ref()"); | 4953 internal_error("func_ref()"); |
4931 } | 4954 } |
4932 | 4955 |