To: vim_dev@googlegroups.com Subject: Patch 8.2.3812 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3812 Problem: Vim9: leaking memory in numbered function test. Solution: Skip "g:" when checking for numbered function. Clean up after errors properly. Files: src/userfunc.c *** ../vim-8.2.3811/src/userfunc.c 2021-12-14 12:06:12.533925687 +0000 --- src/userfunc.c 2021-12-15 12:01:49.976571694 +0000 *************** *** 2136,2141 **** --- 2136,2151 ---- } /* + * Return TRUE if "name" is a numbered function, ignoring a "g:" prefix. + */ + static int + numbered_function(char_u *name) + { + return isdigit(*name) + || (name[0] == 'g' && name[1] == ':' && isdigit(name[2])); + } + + /* * There are two kinds of function names: * 1. ordinary names, function defined with :function or :def * 2. numbered functions and lambdas *************** *** 2146,2152 **** int func_name_refcount(char_u *name) { ! return isdigit(*name) || *name == '<'; } /* --- 2156,2162 ---- int func_name_refcount(char_u *name) { ! return numbered_function(name) || *name == '<'; } /* *************** *** 3956,3961 **** --- 3966,3973 ---- int flags = 0; char_u *ret_type = NULL; ufunc_T *fp = NULL; + int fp_allocated = FALSE; + int free_fp = FALSE; int overwrite = FALSE; dictitem_T *v; funcdict_T fudi; *************** *** 4460,4465 **** --- 4472,4478 ---- fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); if (fp == NULL) goto erret; + fp_allocated = TRUE; if (fudi.fd_dict != NULL) { *************** *** 4490,4510 **** // behave like "dict" was used flags |= FC_DICT; } - - // insert the new function in the function list - set_ufunc_name(fp, name); - if (overwrite) - { - hi = hash_find(&func_hashtab, name); - hi->hi_key = UF2HIKEY(fp); - } - else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) - { - vim_free(fp); - fp = NULL; - goto erret; - } - fp->uf_refcount = 1; } fp->uf_args = newargs; fp->uf_def_args = default_args; --- 4503,4508 ---- *************** *** 4527,4533 **** if (parse_argument_types(fp, &argtypes, varargs) == FAIL) { SOURCING_LNUM = lnum_save; ! goto errret_2; } varargs = FALSE; --- 4525,4532 ---- if (parse_argument_types(fp, &argtypes, varargs) == FAIL) { SOURCING_LNUM = lnum_save; ! free_fp = fp_allocated; ! goto erret; } varargs = FALSE; *************** *** 4535,4540 **** --- 4534,4540 ---- if (parse_return_type(fp, ret_type) == FAIL) { SOURCING_LNUM = lnum_save; + free_fp = fp_allocated; goto erret; } SOURCING_LNUM = lnum_save; *************** *** 4542,4548 **** --- 4542,4566 ---- else fp->uf_def_status = UF_NOT_COMPILED; + if (fp_allocated) + { + // insert the new function in the function list + set_ufunc_name(fp, name); + if (overwrite) + { + hi = hash_find(&func_hashtab, name); + hi->hi_key = UF2HIKEY(fp); + } + else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) + { + free_fp = TRUE; + goto erret; + } + fp->uf_refcount = 1; + } + fp->uf_lines = newlines; + newlines.ga_data = NULL; if ((flags & FC_CLOSURE) != 0) { if (register_closure(fp) == FAIL) *************** *** 4593,4598 **** --- 4611,4621 ---- ga_clear_strings(&newlines); if (fp != NULL) VIM_CLEAR(fp->uf_arg_types); + if (free_fp) + { + vim_free(fp); + fp = NULL; + } ret_free: ga_clear_strings(&argtypes); vim_free(line_to_free); *************** *** 4813,4819 **** if (eap->nextcmd != NULL) *p = NUL; ! if (isdigit(*name) && fudi.fd_dict == NULL) { if (!eap->skip) semsg(_(e_invarg2), eap->arg); --- 4836,4842 ---- if (eap->nextcmd != NULL) *p = NUL; ! if (numbered_function(name) && fudi.fd_dict == NULL) { if (!eap->skip) semsg(_(e_invarg2), eap->arg); *************** *** 4881,4887 **** if (name == NULL || !func_name_refcount(name)) return; fp = find_func(name, FALSE, NULL); ! if (fp == NULL && isdigit(*name)) { #ifdef EXITFREE if (!entered_free_all_mem) --- 4904,4910 ---- if (name == NULL || !func_name_refcount(name)) return; fp = find_func(name, FALSE, NULL); ! if (fp == NULL && numbered_function(name)) { #ifdef EXITFREE if (!entered_free_all_mem) *************** *** 4924,4930 **** fp = find_func(name, FALSE, NULL); if (fp != NULL) ++fp->uf_refcount; ! else if (isdigit(*name)) // Only give an error for a numbered function. // Fail silently, when named or lambda function isn't found. internal_error("func_ref()"); --- 4947,4953 ---- fp = find_func(name, FALSE, NULL); if (fp != NULL) ++fp->uf_refcount; ! else if (numbered_function(name)) // Only give an error for a numbered function. // Fail silently, when named or lambda function isn't found. internal_error("func_ref()"); *** ../vim-8.2.3811/src/version.c 2021-12-14 20:26:49.658164887 +0000 --- src/version.c 2021-12-14 20:55:55.637521221 +0000 *************** *** 751,752 **** --- 751,754 ---- { /* Add new patch number below this line */ + /**/ + 3812, /**/ -- hundred-and-one symptoms of being an internet addict: 35. Your husband tells you he's had that beard for 2 months. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///