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