patch 9.2.0126: String handling can be improved

Commit: 
https://github.com/vim/vim/commit/727f6e2686fb1d06b9591e6de689763a479cc664
Author: John Marriott <[email protected]>
Date:   Mon Mar 9 18:17:22 2026 +0000

    patch 9.2.0126: String handling can be improved
    
    Problem:  String handling can be improved
    Solution: Pass string length where it is known to avoid strlen() calls,
              do a few minor refactors (John Marriott).
    
    This commit changes some calls to function `set_vim_var_string()` to pass
    the string length where it is known or can be easily calculated.
    
    In addition:
    In `evalvars.c`:
      * In function `set_reg_var()` turn variable `regname` into a C string
        because that is how it used.
      * Small cosmetics.
    In `option.c`:
      * Slightly refactor function `apply_optionset_autocmd()` to move some
        variables closer to where they are used.
    In `getchar.c`:
      * Slightly refactor function `do_key_input_pre()`:
        -> change call to `dict_add_string()` to `dict_add_string_len()` and
           pass it the length of `buf`.
        -> only call `get_vim_var_string()` once.
    In `message.c`:
      * Use a `string_T` to store local variable `p`.
    In `normal.c`:
      * Move some variables closer to where they are used.
    
    closes: #19618
    
    Signed-off-by: John Marriott <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/evalvars.c b/src/evalvars.c
index 16dcb0282..9f0cc08c8 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -2845,16 +2845,19 @@ get_vim_var_dict(int idx)
     void
 set_vim_var_char(int c)
 {
-    char_u     buf[MB_MAXBYTES + 1];
+    char_u  buf[MB_MAXBYTES + 1];
+    size_t  buflen;
 
     if (has_mbyte)
-       buf[(*mb_char2bytes)(c, buf)] = NUL;
+       buflen = (*mb_char2bytes)(c, buf);
     else
     {
        buf[0] = c;
-       buf[1] = NUL;
+       buflen = 1;
     }
-    set_vim_var_string(VV_CHAR, buf, -1);
+    buf[buflen] = NUL;
+
+    set_vim_var_string(VV_CHAR, buf, (int)buflen);
 }
 
 /*
@@ -2999,15 +3002,16 @@ reset_reg_var(void)
     void
 set_reg_var(int c)
 {
-    char_u     regname;
+    char_u  regname[2];
 
     if (c == 0 || c == ' ')
-       regname = '"';
+       regname[0] = '"';
     else
-       regname = c;
+       regname[0] = c;
+    regname[1] = NUL;
     // Avoid free/alloc when the value is already right.
     if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
-       set_vim_var_string(VV_REG, &regname, 1);
+       set_vim_var_string(VV_REG, regname, 1);
 }
 
 /*
@@ -4754,8 +4758,8 @@ setwinvar(typval_T *argvars, int off)
     void
 reset_v_option_vars(void)
 {
-    set_vim_var_string(VV_OPTION_NEW,  NULL, -1);
-    set_vim_var_string(VV_OPTION_OLD,  NULL, -1);
+    set_vim_var_string(VV_OPTION_NEW, NULL, -1);
+    set_vim_var_string(VV_OPTION_OLD, NULL, -1);
     set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1);
     set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1);
     set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 08ff73160..b131697f4 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -2900,24 +2900,26 @@ do_ecmd(
     if ((command != NULL || newlnum > (linenr_T)0)
            && *get_vim_var_str(VV_SWAPCOMMAND) == NUL)
     {
-       int     len;
-       char_u  *p;
+       string_T    val;
+       size_t      valsize;
 
        // Set v:swapcommand for the SwapExists autocommands.
        if (command != NULL)
-           len = (int)STRLEN(command) + 3;
+           valsize = (int)STRLEN(command) + 3;
        else
-           len = 30;
-       p = alloc(len);
-       if (p != NULL)
+           valsize = 30;
+       val.string = alloc(valsize);
+       if (val.string != NULL)
        {
            if (command != NULL)
-               vim_snprintf((char *)p, len, ":%s
", command);
+               val.length = vim_snprintf_safelen((char *)val.string,
+                   valsize, ":%s
", command);
            else
-               vim_snprintf((char *)p, len, "%ldG", (long)newlnum);
-           set_vim_var_string(VV_SWAPCOMMAND, p, -1);
+               val.length = vim_snprintf_safelen((char *)val.string,
+                   valsize, "%ldG", (long)newlnum);
+           set_vim_var_string(VV_SWAPCOMMAND, val.string, (int)val.length);
            did_set_swapcommand = TRUE;
-           vim_free(p);
+           vim_free(val.string);
        }
     }
 #endif
diff --git a/src/ex_eval.c b/src/ex_eval.c
index 369314d22..00e4d5fcf 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -679,12 +679,14 @@ catch_exception(except_T *excp)
     set_vim_var_list(VV_STACKTRACE, excp->stacktrace);
     if (*excp->throw_name != NUL)
     {
+       size_t  IObufflen;
+
        if (excp->throw_lnum != 0)
-           vim_snprintf((char *)IObuff, IOSIZE, _("%s, line %ld"),
+           IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, _("%s, 
line %ld"),
                                    excp->throw_name, (long)excp->throw_lnum);
        else
-           vim_snprintf((char *)IObuff, IOSIZE, "%s", excp->throw_name);
-       set_vim_var_string(VV_THROWPOINT, IObuff, -1);
+           IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, "%s", 
excp->throw_name);
+       set_vim_var_string(VV_THROWPOINT, IObuff, (int)IObufflen);
     }
     else
        // throw_name not set on an exception from a command that was typed.
@@ -730,14 +732,16 @@ finish_exception(except_T *excp)
        set_vim_var_list(VV_STACKTRACE, caught_stack->stacktrace);
        if (*caught_stack->throw_name != NUL)
        {
+           size_t  IObufflen;
+
            if (caught_stack->throw_lnum != 0)
-               vim_snprintf((char *)IObuff, IOSIZE,
+               IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE,
                        _("%s, line %ld"), caught_stack->throw_name,
                        (long)caught_stack->throw_lnum);
            else
-               vim_snprintf((char *)IObuff, IOSIZE, "%s",
+               IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, "%s",
                                                    caught_stack->throw_name);
-           set_vim_var_string(VV_THROWPOINT, IObuff, -1);
+           set_vim_var_string(VV_THROWPOINT, IObuff, (int)IObufflen);
        }
        else
            // throw_name not set on an exception from a command that was
diff --git a/src/fold.c b/src/fold.c
index c6eb08a36..9618c21c6 100644
--- a/src/fold.c
+++ b/src/fold.c
@@ -1950,7 +1950,7 @@ get_foldtext(
            level = (int)sizeof(dashes) - 1;
        vim_memset(dashes, '-', (size_t)level);
        dashes[level] = NUL;
-       set_vim_var_string(VV_FOLDDASHES, dashes, -1);
+       set_vim_var_string(VV_FOLDDASHES, dashes, level);
        set_vim_var_nr(VV_FOLDLEVEL, (long)level);
 
        // skip evaluating 'foldtext' on errors
diff --git a/src/getchar.c b/src/getchar.c
index e825498c5..b4ef9ce82 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2214,6 +2214,7 @@ do_key_input_pre(int c)
 {
     int                res = c;
     char_u     buf[MB_MAXBYTES + 1];
+    size_t     buflen;
     char_u     curr_mode[MODE_MAX_LENGTH];
     int                save_State = State;
     save_v_event_T save_v_event;
@@ -2228,10 +2229,11 @@ do_key_input_pre(int c)
        buf[0] = K_SPECIAL;
        buf[1] = KEY2TERMCAP0(c);
        buf[2] = KEY2TERMCAP1(c);
-       buf[3] = NUL;
+       buflen = 3;
     }
     else
-       buf[(*mb_char2bytes)(c, buf)] = NUL;
+       buflen = (*mb_char2bytes)(c, buf);
+    buf[buflen] = NUL;
 
     typedchars[typedchars_pos] = NUL;
     vim_unescape_csi(typedchars);
@@ -2240,29 +2242,29 @@ do_key_input_pre(int c)
 
     // Lock the text to avoid weird things from happening.
     ++textlock;
-    set_vim_var_string(VV_CHAR, buf, -1);  // set v:char
+    set_vim_var_string(VV_CHAR, buf, (int)buflen);  // set v:char
 
     v_event = get_v_event(&save_v_event);
     (void)dict_add_bool(v_event, "typed", KeyTyped);
-    (void)dict_add_string(v_event, "typedchar", typedchars);
+    (void)dict_add_string_len(v_event, "typedchar", typedchars, 
typedchars_pos);
 
-    if (apply_autocmds(EVENT_KEYINPUTPRE, curr_mode, curr_mode, FALSE, curbuf)
-       && STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0)
+    if (apply_autocmds(EVENT_KEYINPUTPRE, curr_mode, curr_mode, FALSE, curbuf))
     {
+       string_T    v_char;
+
        // Get the value of v:char.  It may be empty or more than one
        // character.  Only use it when changed, otherwise continue with the
        // original character.
-       char_u *v_char;
-       size_t  v_charlen;
-
-       v_char = get_vim_var_str(VV_CHAR);
-       v_charlen = STRLEN(v_char);
-
-       // Convert special bytes when it is special string.
-       if (v_charlen >= 3 && v_char[0] == K_SPECIAL)
-           res = TERMCAP2KEY(v_char[1], v_char[2]);
-       else if (v_charlen > 0)
-           res = PTR2CHAR(v_char);
+       v_char.string = get_vim_var_str(VV_CHAR);
+       if (STRCMP(buf, v_char.string) != 0)
+       {
+           v_char.length = STRLEN(v_char.string);
+           // Convert special bytes when it is special string.
+           if (v_char.length >= 3 && v_char.string[0] == K_SPECIAL)
+               res = TERMCAP2KEY(v_char.string[1], v_char.string[2]);
+           else if (v_char.length > 0)
+               res = PTR2CHAR(v_char.string);
+       }
     }
 
     restore_v_event(v_event, &save_v_event);
diff --git a/src/if_xcmdsrv.c b/src/if_xcmdsrv.c
index dba97be2c..070e0db09 100644
--- a/src/if_xcmdsrv.c
+++ b/src/if_xcmdsrv.c
@@ -311,10 +311,13 @@ DoRegisterName(Display *dpy, char_u *name)
 
     if (!got_x_error)
     {
+       size_t  namelen;
+
+       namelen = STRLEN(name);
 # ifdef FEAT_EVAL
-       set_vim_var_string(VV_SEND_SERVER, name, -1);
+       set_vim_var_string(VV_SEND_SERVER, name, (int)namelen);
 # endif
-       serverName = vim_strsave(name);
+       serverName = vim_strnsave(name, namelen);
        need_maketitle = TRUE;
        return 0;
     }
diff --git a/src/main.c b/src/main.c
index ec046f3b2..10828933d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2849,11 +2849,14 @@ scripterror:
     // one.
     if (parmp->n_commands > 0)
     {
-       p = alloc(STRLEN(parmp->commands[0]) + 3);
+       size_t  plen;
+
+       plen = STRLEN(parmp->commands[0]) + 2;
+       p = alloc(plen + 1);
        if (p != NULL)
        {
            sprintf((char *)p, ":%s
", parmp->commands[0]);
-           set_vim_var_string(VV_SWAPCOMMAND, p, -1);
+           set_vim_var_string(VV_SWAPCOMMAND, p, (int)plen);
            vim_free(p);
        }
     }
diff --git a/src/message.c b/src/message.c
index 85beaa7c7..ac25fe322 100644
--- a/src/message.c
+++ b/src/message.c
@@ -2851,26 +2851,30 @@ inc_msg_scrolled(void)
 #ifdef FEAT_EVAL
     if (*get_vim_var_str(VV_SCROLLSTART) == NUL)
     {
-       char_u      *p = SOURCING_NAME;
+       string_T    p = {SOURCING_NAME, 0};
        char_u      *tofree = NULL;
-       int         len;
 
        // v:scrollstart is empty, set it to the script/function name and line
        // number
-       if (p == NULL)
-           p = (char_u *)_("Unknown");
+       if (p.string == NULL)
+       {
+           p.string = (char_u *)_("Unknown");
+           p.length = STRLEN(p.string);
+       }
        else
        {
-           len = (int)STRLEN(p) + 40;
-           tofree = alloc(len);
+           size_t  tofreesize;
+
+           tofreesize = (int)STRLEN(p.string) + 40;
+           tofree = alloc(tofreesize);
            if (tofree != NULL)
            {
-               vim_snprintf((char *)tofree, len, _("%s line %ld"),
-                                                     p, (long)SOURCING_LNUM);
-               p = tofree;
+               p.length = vim_snprintf_safelen((char *)tofree, tofreesize,
+                   _("%s line %ld"), p.string, (long)SOURCING_LNUM);
+               p.string = tofree;
            }
        }
-       set_vim_var_string(VV_SCROLLSTART, p, -1);
+       set_vim_var_string(VV_SCROLLSTART, p.string, (int)p.length);
        vim_free(tofree);
     }
 #endif
diff --git a/src/normal.c b/src/normal.c
index 42e9eafec..e6923c0bc 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -6492,16 +6492,16 @@ nv_operator(cmdarg_T *cap)
     static void
 set_op_var(int optype)
 {
-    char_u     opchars[3];
-
     if (optype == OP_NOP)
        set_vim_var_string(VV_OP, NULL, 0);
     else
     {
+       char_u  opchars[3];
+
        opchars[0] = get_op_char(optype);
        opchars[1] = get_extra_op_char(optype);
        opchars[2] = NUL;
-       set_vim_var_string(VV_OP, opchars, -1);
+       set_vim_var_string(VV_OP, opchars, 2);
     }
 }
 #endif
diff --git a/src/option.c b/src/option.c
index a56dfa3ae..68de5b557 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3258,41 +3258,49 @@ apply_optionset_autocmd(
        long    newval,
        char    *errmsg)
 {
-    char_u buf_old[12], buf_old_global[12], buf_new[12], buf_type[12];
+    char_u buf_old[12], buf_new[12], buf_type[12];
+    size_t  buf_oldlen;
+    size_t  len;
 
     // Don't do this while starting up, failure or recursively.
     if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL)
        return;
 
-    vim_snprintf((char *)buf_old, sizeof(buf_old), "%ld", oldval);
-    vim_snprintf((char *)buf_old_global, sizeof(buf_old_global), "%ld",
-                                                       oldval_g);
-    vim_snprintf((char *)buf_new, sizeof(buf_new), "%ld", newval);
-    vim_snprintf((char *)buf_type, sizeof(buf_type), "%s",
+    len = vim_snprintf_safelen((char *)buf_new, sizeof(buf_new), "%ld", 
newval);
+    set_vim_var_string(VV_OPTION_NEW, buf_new, (int)len);
+    len = vim_snprintf_safelen((char *)buf_type, sizeof(buf_type), "%s",
                                (opt_flags & OPT_LOCAL) ? "local" : "global");
-    set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
-    set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
-    set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+    set_vim_var_string(VV_OPTION_TYPE, buf_type, (int)len);
+
+    buf_oldlen = vim_snprintf_safelen((char *)buf_old, sizeof(buf_old), "%ld", 
oldval);
+    set_vim_var_string(VV_OPTION_OLD, buf_old, (int)buf_oldlen);
+
     if (opt_flags & OPT_LOCAL)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
-       set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", 
STRLEN_LITERAL("setlocal"));
+       set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, (int)buf_oldlen);
     }
     if (opt_flags & OPT_GLOBAL)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
-       set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", 
STRLEN_LITERAL("setglobal"));
+       set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, (int)buf_oldlen);
     }
     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
-       set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
-       set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
+       char_u  buf_old_global[12];
+       size_t  buf_old_globallen;
+
+       buf_old_globallen = vim_snprintf_safelen((char *)buf_old_global,
+           sizeof(buf_old_global), "%ld", oldval_g);
+
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", 
STRLEN_LITERAL("set"));
+       set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, (int)buf_oldlen);
+       set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, 
(int)buf_old_globallen);
     }
     if (opt_flags & OPT_MODELINE)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
-       set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", 
STRLEN_LITERAL("modeline"));
+       set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, (int)buf_oldlen);
     }
     apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
            NULL, FALSE, NULL);
diff --git a/src/optionstr.c b/src/optionstr.c
index a34d86a01..b94824d45 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -221,32 +221,35 @@ trigger_optionset_string(
        return;
 
     char_u buf_type[7];
+    size_t buf_typelen;
+    size_t oldvallen;
 
-    sprintf((char *)buf_type, "%s",
-           (opt_flags & OPT_LOCAL) ? "local" : "global");
-    set_vim_var_string(VV_OPTION_OLD, oldval, -1);
+    oldvallen = STRLEN(oldval);
+    set_vim_var_string(VV_OPTION_OLD, oldval, (int)oldvallen);
     set_vim_var_string(VV_OPTION_NEW, newval, -1);
-    set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+    buf_typelen = vim_snprintf_safelen((char *)buf_type, sizeof(buf_type),
+       "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
+    set_vim_var_string(VV_OPTION_TYPE, buf_type, (int)buf_typelen);
     if (opt_flags & OPT_LOCAL)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
-       set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", 
STRLEN_LITERAL("setlocal"));
+       set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, (int)oldvallen);
     }
     if (opt_flags & OPT_GLOBAL)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
-       set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", 
STRLEN_LITERAL("setglobal"));
+       set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, (int)oldvallen);
     }
     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", 
STRLEN_LITERAL("set"));
        set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
        set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
     }
     if (opt_flags & OPT_MODELINE)
     {
-       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
-       set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+       set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", 
STRLEN_LITERAL("modeline"));
+       set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, (int)oldvallen);
     }
     apply_autocmds(EVENT_OPTIONSET,
            get_option_fullname(opt_idx), NULL, FALSE,
diff --git a/src/tag.c b/src/tag.c
index be64ea5ff..d3e27e602 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -745,6 +745,9 @@ do_tag(
        else
        {
            int ask_for_selection = FALSE;
+#if defined(FEAT_EVAL)
+           size_t  IObufflen;
+#endif
 
 #ifdef FEAT_CSCOPE
            if (type == DT_CSCOPE && num_matches > 1)
@@ -880,8 +883,8 @@ do_tag(
 
 #if defined(FEAT_EVAL)
            // Let the SwapExists event know what tag we are jumping to.
-           vim_snprintf((char *)IObuff, IOSIZE, ":ta %s
", name);
-           set_vim_var_string(VV_SWAPCOMMAND, IObuff, -1);
+           IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, ":ta %s
", name);
+           set_vim_var_string(VV_SWAPCOMMAND, IObuff, (int)IObufflen);
 #endif
 
            /*
diff --git a/src/version.c b/src/version.c
index f745f3a7d..ff021ff19 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    126,
 /**/
     125,
 /**/

-- 
-- 
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 [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1vzfMl-00Enf4-Q7%40256bit.org.

Raspunde prin e-mail lui