patch 9.1.1063: too many strlen() calls in userfunc.c Commit: https://github.com/vim/vim/commit/b32800f7c51c866dc0e87244eb4902540982309d Author: John Marriott <basil...@internode.on.net> Date: Sat Feb 1 15:25:34 2025 +0100
patch 9.1.1063: too many strlen() calls in userfunc.c Problem: too many strlen() calls in userfunc.c Solution: refactor userfunc.c and remove calls to strlen(), drop set_ufunc_name() and roll it into alloc_ufunc(), check for out-of-memory condition in trans_function_name_ext() (John Marriott) closes: #16537 Signed-off-by: John Marriott <basil...@internode.on.net> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/dict.c b/src/dict.c index 8f0db7edc..7975904da 100644 --- a/src/dict.c +++ b/src/dict.c @@ -544,7 +544,7 @@ dict_add_func(dict_T *d, char *key, ufunc_T *fp) if (item == NULL) return FAIL; item->di_tv.v_type = VAR_FUNC; - item->di_tv.vval.v_string = vim_strsave(fp->uf_name); + item->di_tv.vval.v_string = vim_strnsave(fp->uf_name, fp->uf_namelen); if (dict_add(d, item) == FAIL) { dictitem_free(item); diff --git a/src/eval.c b/src/eval.c index 387f61d87..9a140c166 100644 --- a/src/eval.c +++ b/src/eval.c @@ -7100,7 +7100,7 @@ handle_subscript( else { rettv->v_type = VAR_FUNC; - rettv->vval.v_string = vim_strsave(ufunc->uf_name); + rettv->vval.v_string = vim_strnsave(ufunc->uf_name, ufunc->uf_namelen); } continue; } diff --git a/src/evalvars.c b/src/evalvars.c index e0ca4b81d..1b11f2847 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -3135,7 +3135,7 @@ eval_variable( // assumed. rettv->vval.v_string = vim_strsave(name); else - rettv->vval.v_string = vim_strsave(ufunc->uf_name); + rettv->vval.v_string = vim_strnsave(ufunc->uf_name, ufunc->uf_namelen); if (rettv->vval.v_string != NULL) func_ref(ufunc->uf_name); } diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro index cdcf017d3..a0f04b206 100644 --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -3,6 +3,7 @@ void func_init(void); hashtab_T *func_tbl_get(void); char_u *make_ufunc_name_readable(char_u *name, char_u *buf, size_t bufsize); char_u *get_lambda_name(void); +size_t get_lambda_name_len(void); char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state); int get_lambda_tv(char_u **arg, typval_T *rettv, int types_optional, evalarg_T *evalarg); char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, type_T **type, int no_autoload, int new_function, int *found_var); diff --git a/src/structs.h b/src/structs.h index 69494dd9b..7c51c72bd 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1934,6 +1934,7 @@ struct ufunc_S char_u *uf_name_exp; // if "uf_name[]" starts with SNR the name with // "<SNR>" as a string, otherwise NULL + size_t uf_namelen; // length of uf_name (excluding the NUL) char_u uf_name[4]; // name of function (actual size equals name); // can start with <SNR>123_ (<SNR> is K_SPECIAL // KS_EXTRA KE_SNR) diff --git a/src/userfunc.c b/src/userfunc.c index 91c971e8f..81f1f284e 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -171,9 +171,13 @@ one_function_arg( if (!skip) { if (type == NULL && types_optional) + { // lambda arguments default to "any" type - type = vim_strsave((char_u *) - (is_vararg ? "list<any>" : "any")); + if (is_vararg) + type = vim_strnsave((char_u *)"list<any>", 9); + else + type = vim_strnsave((char_u *)"any", 3); + } ((char_u **)argtypes->ga_data)[argtypes->ga_len++] = type; ((int8_T *)arg_objm->ga_data)[arg_objm->ga_len++] = FALSE; } @@ -346,7 +350,7 @@ get_function_args( if (ga_grow(default_args, 1) == FAIL) goto err_ret; - char_u *expr = vim_strsave((char_u *)"v:none"); + char_u *expr = vim_strnsave((char_u *)"v:none", 6); if (expr == NULL) goto err_ret; ((char_u **)(default_args->ga_data)) @@ -373,7 +377,7 @@ get_function_args( { // TODO: use the actual type ((char_u **)argtypes->ga_data)[argtypes->ga_len++] = - vim_strsave((char_u *)"any"); + vim_strnsave((char_u *)"any", 3); ((int8_T *)arg_objm->ga_data)[arg_objm->ga_len++] = TRUE; // Add a line to the function body for the assignment. @@ -656,24 +660,6 @@ register_closure(ufunc_T *fp) return OK; } - static void -set_ufunc_name(ufunc_T *fp, char_u *name) -{ - // Add a type cast to avoid a warning for an overflow, the uf_name[] array - // actually extends beyond the struct. - STRCPY((void *)fp->uf_name, name); - - if (name[0] == K_SPECIAL) - { - fp->uf_name_exp = alloc(STRLEN(name) + 3); - if (fp->uf_name_exp != NULL) - { - STRCPY(fp->uf_name_exp, "<SNR>"); - STRCAT(fp->uf_name_exp, fp->uf_name + 3); - } - } -} - /* * If "name" starts with K_SPECIAL and "buf[bufsize]" is big enough * return "buf" filled with a readable function name. @@ -699,14 +685,34 @@ make_ufunc_name_readable(char_u *name, char_u *buf, size_t bufsize) /* * Get a name for a lambda. Returned in static memory. */ +static char_u lambda_name[8 + NUMBUFLEN]; +static size_t lambda_namelen = 0; + char_u * get_lambda_name(void) { - static char_u name[30]; - static int lambda_no = 0; + static int lambda_no = 0; + int n; - sprintf((char*)name, "<lambda>%d", ++lambda_no); - return name; + n = vim_snprintf((char *)lambda_name, sizeof(lambda_name), "<lambda>%d", ++lambda_no); + if (n < 1) + lambda_namelen = 0; + else + if (n >= (int)sizeof(lambda_name)) + lambda_namelen = sizeof(lambda_name) - 1; + else + lambda_namelen = (size_t)n; + + return lambda_name; +} + +/* + * Get the length of the last lambda name. + */ + size_t +get_lambda_name_len(void) +{ + return lambda_namelen; } /* @@ -714,12 +720,32 @@ get_lambda_name(void) * Makes sure the size is right. */ static ufunc_T * -alloc_ufunc(char_u *name) +alloc_ufunc(char_u *name, size_t namelen) { + size_t len; + ufunc_T *fp; + // When the name is short we need to make sure we allocate enough bytes for // the whole struct, including any padding. - size_t len = offsetof(ufunc_T, uf_name) + STRLEN(name) + 1; - return alloc_clear(len < sizeof(ufunc_T) ? sizeof(ufunc_T) : len); + len = offsetof(ufunc_T, uf_name) + namelen + 1; + fp = alloc_clear(len < sizeof(ufunc_T) ? sizeof(ufunc_T) : len); + if (fp != NULL) + { + // Add a type cast to avoid a warning for an overflow, the uf_name[] array + // can actually extend beyond the struct. + STRCPY((void *)fp->uf_name, name); + fp->uf_namelen = namelen; + + if (name[0] == K_SPECIAL) + { + len = namelen + 3; // including +1 for NUL + fp->uf_name_exp = alloc(len); + if (fp->uf_name_exp != NULL) + vim_snprintf((char *)fp->uf_name_exp, len, "<SNR>%s", fp->uf_name + 3); + } + } + + return fp; } #if defined(FEAT_LUA) || defined(PROTO) @@ -731,9 +757,10 @@ alloc_ufunc(char_u *name) register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state) { char_u *name = get_lambda_name(); + size_t namelen = get_lambda_name_len(); ufunc_T *fp; - fp = alloc_ufunc(name); + fp = alloc_ufunc(name, namelen); if (fp == NULL) return NULL; @@ -747,7 +774,6 @@ register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state) fp->uf_cb_free = cb_free; fp->uf_cb_state = state; - set_ufunc_name(fp, name); hash_add(&func_hashtab, UF2HIKEY(fp), "add C function"); return name; @@ -976,6 +1002,7 @@ get_function_body( int heredoc_concat_len = 0; garray_T heredoc_ga; char_u *heredoc_trimmed = NULL; + size_t heredoc_trimmedlen = 0; ga_init2(&heredoc_ga, 1, 500); @@ -1059,19 +1086,20 @@ get_function_body( if (heredoc_trimmed == NULL || (is_heredoc && skipwhite(theline) == theline) || STRNCMP(theline, heredoc_trimmed, - STRLEN(heredoc_trimmed)) == 0) + heredoc_trimmedlen) == 0) { if (heredoc_trimmed == NULL) p = theline; else if (is_heredoc) p = skipwhite(theline) == theline - ? theline : theline + STRLEN(heredoc_trimmed); + ? theline : theline + heredoc_trimmedlen; else - p = theline + STRLEN(heredoc_trimmed); + p = theline + heredoc_trimmedlen; if (STRCMP(p, skip_until) == 0) { VIM_CLEAR(skip_until); VIM_CLEAR(heredoc_trimmed); + heredoc_trimmedlen = 0; getline_options = vim9_function ? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT; is_heredoc = FALSE; @@ -1271,7 +1299,7 @@ get_function_body( || (p[2] == 's' && (!ASCII_ISALPHA(p[3]) || p[3] == 'e')))))))) - skip_until = vim_strsave((char_u *)"."); + skip_until = vim_strnsave((char_u *)".", 1); // Check for ":python <<EOF", ":tcl <<EOF", etc. arg = skipwhite(skiptowhite(p)); @@ -1298,11 +1326,13 @@ get_function_body( { // Ignore leading white space. p = skipwhite(p + 4); - heredoc_trimmed = vim_strnsave(theline, - skipwhite(theline) - theline); + heredoc_trimmedlen = skipwhite(theline) - theline; + heredoc_trimmed = vim_strnsave(theline, heredoc_trimmedlen); + if (heredoc_trimmed == NULL) + heredoc_trimmedlen = 0; } if (*p == NUL) - skip_until = vim_strsave((char_u *)"."); + skip_until = vim_strnsave((char_u *)".", 1); else skip_until = vim_strnsave(p, skiptowhite(p) - p); getline_options = GETLINE_NONE; @@ -1344,8 +1374,10 @@ get_function_body( { // Ignore leading white space. p = skipwhite(p + 4); - heredoc_trimmed = vim_strnsave(theline, - skipwhite(theline) - theline); + heredoc_trimmedlen = skipwhite(theline) - theline; + heredoc_trimmed = vim_strnsave(theline, heredoc_trimmedlen); + if (heredoc_trimmed == NULL) + heredoc_trimmedlen = 0; continue; } if (STRNCMP(p, "eval", 4) == 0) @@ -1374,7 +1406,7 @@ get_function_body( // to be used for the instruction later. ga_concat(&heredoc_ga, theline); ga_concat(&heredoc_ga, (char_u *)" "); - p = vim_strsave((char_u *)""); + p = vim_strnsave((char_u *)"", 0); } else { @@ -1437,6 +1469,7 @@ lambda_function_body( int ret = FAIL; partial_T *pt; char_u *name; + size_t namelen; int lnum_save = -1; linenr_T sourcing_lnum_top = SOURCING_LNUM; char_u *line_arg = NULL; @@ -1498,8 +1531,12 @@ lambda_function_body( // Insert NL characters at the start of each line, the string will // be split again later in .get_lambda_tv(). if (*p == NUL || vim9_comment_start(p)) + { p = (char_u *)""; - plen = STRLEN(p); + plen = 0; + } + else + plen = STRLEN(p); pnl = vim_strnsave((char_u *)" ", plen + 1); if (pnl != NULL) mch_memmove(pnl + 1, p, plen + 1); @@ -1509,12 +1546,17 @@ lambda_function_body( if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL) goto erret; if (eap.nextcmd != NULL) + { // more is following after the "}", which was skipped last = cmdline; + plen = STRLEN(last); + } else + { // nothing is following the "}" last = (char_u *)"}"; - plen = STRLEN(last); + plen = 1; + } pnl = vim_strnsave((char_u *)" ", plen + 1); if (pnl != NULL) mch_memmove(pnl + 1, last, plen + 1); @@ -1546,10 +1588,10 @@ lambda_function_body( } name = get_lambda_name(); - ufunc = alloc_ufunc(name); + namelen = get_lambda_name_len(); + ufunc = alloc_ufunc(name, namelen); if (ufunc == NULL) goto erret; - set_ufunc_name(ufunc, name); if (hash_add(&func_hashtab, UF2HIKEY(ufunc), "add function") == FAIL) goto erret; ufunc->uf_flags = FC_LAMBDA; @@ -1755,8 +1797,9 @@ get_lambda_tv( char_u *p; char_u *line_end; char_u *name = get_lambda_name(); + size_t namelen = get_lambda_name_len(); - fp = alloc_ufunc(name); + fp = alloc_ufunc(name, namelen); if (fp == NULL) goto errret; fp->uf_def_status = UF_NOT_COMPILED; @@ -1804,7 +1847,6 @@ get_lambda_tv( flags |= FC_NOARGS; fp->uf_refcount = 1; - set_ufunc_name(fp, name); fp->uf_args = newargs; ga_init(&fp->uf_def_args); if (types_optional) @@ -1875,10 +1917,13 @@ errret: { ga_clear_strings(&argtypes); ga_clear(&arg_objm); - if (fp != NULL) - vim_free(fp->uf_arg_types); } - vim_free(fp); + if (fp != NULL) + { + vim_free(fp->uf_arg_types); + vim_free(fp->uf_name_exp); + vim_free(fp); + } vim_free(pt); vim_free(tofree2); eval_lavars_used = old_eval_lavars; @@ -2184,44 +2229,48 @@ fname_trans_sid( char_u **tofree, funcerror_T *error) { - int llen; + char_u *script_name; char_u *fname; - int i; + size_t fnamelen; + size_t fname_buflen; - llen = eval_fname_script(name); - if (llen == 0) + script_name = name + eval_fname_script(name); + if (script_name == name) return name; // no prefix fname_buf[0] = K_SPECIAL; fname_buf[1] = KS_EXTRA; fname_buf[2] = (int)KE_SNR; - i = 3; - if (eval_fname_sid(name)) // "<SID>" or "s:" + fname_buflen = 3; + if (!eval_fname_sid(name)) // "<SID>" or "s:" + fname_buf[fname_buflen] = NUL; + else { if (current_sctx.sc_sid <= 0) *error = FCERR_SCRIPT; else { - sprintf((char *)fname_buf + 3, "%ld_", + fname_buflen += vim_snprintf((char *)fname_buf + 3, + FLEN_FIXED - 3, + "%ld_", (long)current_sctx.sc_sid); - i = (int)STRLEN(fname_buf); } } - if (i + STRLEN(name + llen) < FLEN_FIXED) + fnamelen = fname_buflen + STRLEN(script_name); + if (fnamelen < FLEN_FIXED) { - STRCPY(fname_buf + i, name + llen); + STRCPY(fname_buf + fname_buflen, script_name); fname = fname_buf; } else { - fname = alloc(i + STRLEN(name + llen) + 1); + fname = alloc(fnamelen + 1); if (fname == NULL) *error = FCERR_OTHER; else { *tofree = fname; - mch_memmove(fname, fname_buf, (size_t)i); - STRCPY(fname + i, name + llen); + vim_snprintf((char *)fname, fnamelen + 1, "%s%s", fname_buf, script_name); } } return fname; @@ -2391,7 +2440,7 @@ func_is_global(ufunc_T *ufunc) int func_requires_g_prefix(ufunc_T *ufunc) { - return ufunc->uf_name[0] != K_SPECIAL + return func_is_global(ufunc) && (ufunc->uf_flags & FC_LAMBDA) == 0 && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL && !SAFE_isdigit(ufunc->uf_name[0]); @@ -2402,16 +2451,17 @@ func_requires_g_prefix(ufunc_T *ufunc) * "buf" must be able to hold the function name plus three bytes. * Takes care of script-local function names. */ - static void -cat_func_name(char_u *buf, ufunc_T *fp) + static int +cat_func_name(char_u *buf, size_t bufsize, ufunc_T *fp) { + int len; + if (!func_is_global(fp)) - { - STRCPY(buf, "<SNR>"); - STRCAT(buf, fp->uf_name + 3); - } + len = vim_snprintf((char *)buf, bufsize, "<SNR>%s", fp->uf_name + 3); else - STRCPY(buf, fp->uf_name); + len = vim_snprintf((char *)buf, bufsize, "%s", fp->uf_name); + + return (len >= (int)bufsize) ? (int)bufsize - 1 : len; } /* @@ -2773,7 +2823,7 @@ copy_lambda_to_global_func( return FAIL; } - fp = alloc_ufunc(global); + fp = alloc_ufunc(global, STRLEN(global)); if (fp == NULL) return FAIL; @@ -2805,9 +2855,6 @@ copy_lambda_to_global_func( fp->uf_refcount = 1; - fp->uf_name_exp = NULL; - set_ufunc_name(fp, global); - hash_add(&func_hashtab, UF2HIKEY(fp), "copy lambda"); // the referenced dfunc_T is now used one more time @@ -2943,6 +2990,7 @@ call_user_func( int islambda = FALSE; char_u numbuf[NUMBUFLEN]; char_u *name; + size_t namelen; typval_T *tv_to_free[MAX_FUNC_ARGS]; int tv_to_free_len = 0; #ifdef FEAT_PROFILE @@ -3099,6 +3147,8 @@ call_user_func( break; } } + + namelen = STRLEN(name); } else { @@ -3107,10 +3157,10 @@ call_user_func( break; // "..." argument a:1, a:2, etc. - sprintf((char *)numbuf, "%d", ai + 1); + namelen = vim_snprintf((char *)numbuf, sizeof(numbuf), "%d", ai + 1); name = numbuf; } - if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) + if (fixvar_idx < FIXVAR_CNT && namelen <= VAR_SHORT_LEN) { v = &fc->fc_fixvar[fixvar_idx++].var; v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; @@ -3491,8 +3541,7 @@ delete_script_functions(int sid) buf[0] = K_SPECIAL; buf[1] = KS_EXTRA; buf[2] = (int)KE_SNR; - sprintf((char *)buf + 3, "%d_", sid); - len = STRLEN(buf); + len = 3 + vim_snprintf((char *)buf + 3, sizeof(buf) - 3, "%d_", sid); while (todo > 0) { @@ -4388,7 +4437,7 @@ trans_function_name_ext( { if (ufunc != NULL) *ufunc = lv.ll_ufunc; - name = vim_strsave(lv.ll_ufunc->uf_name); + name = vim_strnsave(lv.ll_ufunc->uf_name, lv.ll_ufunc->uf_namelen); *pp = end; goto theend; } @@ -4485,7 +4534,7 @@ trans_function_name_ext( { name = vim_strsave(name); *pp = end; - if (STRNCMP(name, "<SNR>", 5) == 0) + if (name != NULL && STRNCMP(name, "<SNR>", 5) == 0) { // Change "<SNR>" to the byte sequence. name[0] = K_SPECIAL; @@ -4567,17 +4616,19 @@ trans_function_name_ext( && eval_fname_sid(lv.ll_exp_name)) || eval_fname_sid(*pp)) { + size_t sid_buflen; + // It's script-local, "s:" or "<SID>" if (current_sctx.sc_sid <= 0) { emsg(_(e_using_sid_not_in_script_context)); goto theend; } - sprintf((char *)sid_buf, "%ld_", (long)current_sctx.sc_sid); + sid_buflen = vim_snprintf((char *)sid_buf, sizeof(sid_buf), "%ld_", (long)current_sctx.sc_sid); if (vim9_local) - extra = 3 + (int)STRLEN(sid_buf); + extra = 3 + (int)sid_buflen; else - lead += (int)STRLEN(sid_buf); + lead += (int)sid_buflen; } } // The function name must start with an upper case letter (unless it is a @@ -4664,8 +4715,10 @@ untrans_function_name(char_u *name) get_scriptlocal_funcname(char_u *funcname) { char sid_buf[25]; + size_t sid_buflen; int off; char_u *newname; + size_t newnamesize; char_u *p = funcname; if (funcname == NULL) @@ -4696,13 +4749,13 @@ get_scriptlocal_funcname(char_u *funcname) return NULL; } // Expand s: prefix into <SNR>nr_<name> - vim_snprintf(sid_buf, sizeof(sid_buf), "<SNR>%ld_", + sid_buflen = vim_snprintf(sid_buf, sizeof(sid_buf), "<SNR>%ld_", (long)current_sctx.sc_sid); - newname = alloc(STRLEN(sid_buf) + STRLEN(p + off) + 1); + newnamesize = sid_buflen + STRLEN(p + off) + 1; + newname = alloc(newnamesize); if (newname == NULL) return NULL; - STRCPY(newname, sid_buf); - STRCAT(newname, p + off); + vim_snprintf((char *)newname, newnamesize, "%s%s", sid_buf, p + off); return newname; } @@ -4811,6 +4864,7 @@ define_function( int c; int saved_did_emsg = FALSE; char_u *name = name_arg; + size_t namelen = 0; int is_global = FALSE; char_u *p; char_u *arg; @@ -5107,7 +5161,7 @@ define_function( // In Vim9 script a function cannot have the same name as a // variable. if (vim9script && *arg == K_SPECIAL - && eval_variable(name_base, (int)STRLEN(name_base), 0, NULL, + && eval_variable(name_base, i, 0, NULL, NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT + EVAL_VAR_NO_FUNC) == OK) { @@ -5252,7 +5306,7 @@ define_function( */ if (fudi.fd_dict != NULL) { - char numbuf[20]; + char numbuf[NUMBUFLEN]; fp = NULL; if (fudi.fd_newkey == NULL && !eap->forceit) @@ -5273,8 +5327,8 @@ define_function( // Give the function a sequential number. Can only be used with a // Funcref! vim_free(name); - sprintf(numbuf, "%d", ++func_nr); - name = vim_strsave((char_u *)numbuf); + namelen = vim_snprintf(numbuf, sizeof(numbuf), "%d", ++func_nr); + name = vim_strnsave((char_u *)numbuf, namelen); if (name == NULL) goto erret; } @@ -5373,6 +5427,7 @@ define_function( // redefine existing function, keep the expanded name VIM_CLEAR(name); + namelen = 0; fp->uf_name_exp = NULL; func_clear_items(fp); fp->uf_name_exp = exp_name; @@ -5421,7 +5476,9 @@ define_function( } } - fp = alloc_ufunc(name); + if (namelen == 0) + namelen = STRLEN(name); + fp = alloc_ufunc(name, namelen); if (fp == NULL) goto erret; fp_allocated = TRUE; @@ -5448,7 +5505,7 @@ define_function( // overwrite existing dict entry clear_tv(&fudi.fd_di->di_tv); fudi.fd_di->di_tv.v_type = VAR_FUNC; - fudi.fd_di->di_tv.vval.v_string = vim_strsave(name); + fudi.fd_di->di_tv.vval.v_string = vim_strnsave(name, namelen); // behave like "dict" was used flags |= FC_DICT; @@ -5506,7 +5563,6 @@ define_function( if (fp_allocated) { // insert the new function in the function list - set_ufunc_name(fp, name); if (overwrite) { hi = hash_find(&func_hashtab, name); @@ -5581,6 +5637,7 @@ errret_2: { VIM_CLEAR(fp->uf_arg_types); VIM_CLEAR(fp->uf_va_name); + VIM_CLEAR(fp->uf_name_exp); clear_func_type_list(&fp->uf_type_list, &fp->uf_func_type); } if (free_fp) @@ -5918,6 +5975,8 @@ get_user_func_name(expand_T *xp, int idx) } if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used) { + int len; + if (done++ > 0) ++hi; while (HASHITEM_EMPTY(hi)) @@ -5929,16 +5988,19 @@ get_user_func_name(expand_T *xp, int idx) || STRNCMP(fp->uf_name, "<lambda>", 8) == 0) return (char_u *)""; - if (STRLEN(fp->uf_name) + 4 >= IOSIZE) + if (fp->uf_namelen + 4 >= IOSIZE) return fp->uf_name; // prevents overflow - cat_func_name(IObuff, fp); + len = cat_func_name(IObuff, IOSIZE, fp); if (xp->xp_context != EXPAND_USER_FUNC && xp->xp_context != EXPAND_DISASSEMBLE) { - STRCAT(IObuff, "("); + STRCPY(IObuff + len, "("); if (!has_varargs(fp) && fp->uf_args.ga_len == 0) - STRCAT(IObuff, ")"); + { + ++len; + STRCPY(IObuff + len, ")"); + } } return IObuff; } @@ -5955,7 +6017,7 @@ get_user_func_name(expand_T *xp, int idx) ufunc_T * copy_function(ufunc_T *fp) { - ufunc_T *ufunc = alloc_ufunc(fp->uf_name); + ufunc_T *ufunc = alloc_ufunc(fp->uf_name, fp->uf_namelen); if (ufunc == NULL) return NULL; @@ -6004,8 +6066,6 @@ copy_function(ufunc_T *fp) ga_copy_strings(&fp->uf_lines, &ufunc->uf_lines); ufunc->uf_refcount = 1; - ufunc->uf_name_exp = NULL; - STRCPY(ufunc->uf_name, fp->uf_name); return ufunc; } @@ -6760,20 +6820,31 @@ discard_pending_return(void *rettv) get_return_cmd(void *rettv) { char_u *s = NULL; - char_u *tofree = NULL; - char_u numbuf[NUMBUFLEN]; + size_t slen = 0; + size_t IObufflen; if (rettv != NULL) + { + char_u *tofree = NULL; + char_u numbuf[NUMBUFLEN]; + s = echo_string((typval_T *)rettv, &tofree, numbuf, 0); + vim_free(tofree); + } if (s == NULL) s = (char_u *)""; + else + slen = STRLEN(s); STRCPY(IObuff, ":return "); STRNCPY(IObuff + 8, s, IOSIZE - 8); - if (STRLEN(s) + 8 >= IOSIZE) + IObufflen = 8 + slen; + if (slen + 8 >= IOSIZE) + { STRCPY(IObuff + IOSIZE - 4, "..."); - vim_free(tofree); - return vim_strsave(IObuff); + IObufflen += 3; + } + return vim_strnsave(IObuff, IObufflen); } /* diff --git a/src/version.c b/src/version.c index d59ce56b7..e785b4228 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1063, /**/ 1062, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 29b6414c4..aa3e17ef6 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1034,6 +1034,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free) int off; char_u *func_name; char_u *lambda_name; + size_t lambda_namelen; ufunc_T *ufunc; int r = FAIL; compiletype_T compile_type; @@ -1092,7 +1093,9 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free) eap->forceit = FALSE; // We use the special <Lamba>99 name, but it's not really a lambda. - lambda_name = vim_strsave(get_lambda_name()); + lambda_name = get_lambda_name(); + lambda_namelen = get_lambda_name_len(); + lambda_name = vim_strnsave(lambda_name, lambda_namelen); if (lambda_name == NULL) return NULL; @@ -3884,7 +3887,7 @@ add_def_function(ufunc_T *ufunc) dfunc->df_idx = def_functions.ga_len; ufunc->uf_dfunc_idx = dfunc->df_idx; dfunc->df_ufunc = ufunc; - dfunc->df_name = vim_strsave(ufunc->uf_name); + dfunc->df_name = vim_strnsave(ufunc->uf_name, ufunc->uf_namelen); ga_init2(&dfunc->df_var_names, sizeof(char_u *), 10); ++dfunc->df_refcount; ++def_functions.ga_len; diff --git a/src/vim9instr.c b/src/vim9instr.c index 4368e3c2d..b51903950 100644 --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -1445,7 +1445,7 @@ generate_FUNCREF( } } if (ufunc->uf_def_status == UF_NOT_COMPILED || cl != NULL) - extra->fre_func_name = vim_strsave(ufunc->uf_name); + extra->fre_func_name = vim_strnsave(ufunc->uf_name, ufunc->uf_namelen); if (ufunc->uf_def_status != UF_NOT_COMPILED && cl == NULL) { if (isn_idx == NULL && ufunc->uf_def_status == UF_TO_BE_COMPILED) @@ -1912,7 +1912,7 @@ generate_CALL( { // A user function may be deleted and redefined later, can't use the // ufunc pointer, need to look it up again at runtime. - isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name); + isn->isn_arg.ufunc.cuf_name = vim_strnsave(ufunc->uf_name, ufunc->uf_namelen); isn->isn_arg.ufunc.cuf_argcount = argcount; } -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1teEVX-00GOhG-OX%40256bit.org.