patch 9.1.1467: too many strlen() calls

Commit: 
https://github.com/vim/vim/commit/fff0132399082b7d012d0c1291cf0c6c99e200ff
Author: John Marriott <basil...@internode.on.net>
Date:   Wed Jun 18 18:15:31 2025 +0200

    patch 9.1.1467: too many strlen() calls
    
    Problem:  too many strlen() calls
    Solution: Change expand_env() to return string length
              (John Marriott)
    
    This commit does the following changes:
    - In expand_env_esc():
      - return the length of the returned dst string.
      - refactor to remove some calls to STRLEN() and STRCAT()
      - add check for out-of-memory condition.
    - Change call sites in various source files to use the return value
    
    closes: #17561
    
    Signed-off-by: John Marriott <basil...@internode.on.net>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/fileio.c b/src/fileio.c
index 2c6c40ed3..c87ae4d46 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5351,14 +5351,13 @@ vim_tempname(
            long        nr;
            long        off;
 # endif
+           size_t      itmplen;
 
            // Expand $TMP, leave room for "/v1100000/999999999".
            // Skip the directory check if the expansion fails.
-           expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
+           itmplen = expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
            if (itmp[0] != '$' && mch_isdir(itmp))
            {
-               size_t  itmplen = STRLEN(itmp);
-
                // directory exists
                if (!after_pathsep(itmp, itmp + itmplen))
                {
diff --git a/src/findfile.c b/src/findfile.c
index 49def2fe0..0f5f2dc62 100644
--- a/src/findfile.c
+++ b/src/findfile.c
@@ -1820,11 +1820,10 @@ find_file_in_path_option(
        // copy file name into NameBuff, expanding environment variables
        save_char = ptr[len];
        ptr[len] = NUL;
-       expand_env_esc(ptr, NameBuff, MAXPATHL, FALSE, TRUE, NULL);
+       file_to_findlen = expand_env_esc(ptr, NameBuff, MAXPATHL, FALSE, TRUE, 
NULL);
        ptr[len] = save_char;
 
        vim_free(*file_to_find);
-       file_to_findlen = STRLEN(NameBuff);
        *file_to_find = vim_strnsave(NameBuff, file_to_findlen);
        if (*file_to_find == NULL)      // out of memory
        {
diff --git a/src/if_cscope.c b/src/if_cscope.c
index 6b0f92092..86bfbd81b 100644
--- a/src/if_cscope.c
+++ b/src/if_cscope.c
@@ -548,8 +548,7 @@ cs_add_common(
     if ((fname = alloc(MAXPATHL + 1)) == NULL)
        goto add_err;
 
-    expand_env((char_u *)arg1, (char_u *)fname, MAXPATHL);
-    len = STRLEN(fname);
+    len = expand_env((char_u *)arg1, (char_u *)fname, MAXPATHL);
     fbuf = (char_u *)fname;
     (void)modify_fname((char_u *)":p", FALSE, &usedlen,
                                              (char_u **)&fname, &fbuf, &len);
@@ -829,6 +828,7 @@ cs_create_connection(int i)
     int                cmdlen;
     int                len;
     char       *prog, *cmd, *ppath = NULL;
+    size_t     proglen;
 #ifdef MSWIN
     int                fd;
     SECURITY_ATTRIBUTES sa;
@@ -916,10 +916,10 @@ err_closing:
            goto err_closing;
 #endif
        }
-       expand_env(p_csprg, (char_u *)prog, MAXPATHL);
+       proglen = expand_env(p_csprg, (char_u *)prog, MAXPATHL);
 
        // alloc space to hold the cscope command
-       cmdlen = (int)(strlen(prog) + strlen(csinfo[i].fname) + 32);
+       cmdlen = (int)(proglen + strlen(csinfo[i].fname) + 32);
        if (csinfo[i].ppath)
        {
            // expand the prepend path for env var's
@@ -933,9 +933,7 @@ err_closing:
                goto err_closing;
 #endif
            }
-           expand_env((char_u *)csinfo[i].ppath, (char_u *)ppath, MAXPATHL);
-
-           cmdlen += (int)strlen(ppath);
+           cmdlen += (int)expand_env((char_u *)csinfo[i].ppath, (char_u 
*)ppath, MAXPATHL);
        }
 
        if (csinfo[i].flags)
diff --git a/src/mark.c b/src/mark.c
index 2b0391981..9bab352a8 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -540,10 +540,9 @@ fname2fnum(xfmark_T *fm)
 #endif
                ))
     {
-       int len;
+       size_t len;
 
-       expand_env((char_u *)"~/", NameBuff, MAXPATHL);
-       len = (int)STRLEN(NameBuff);
+       len = expand_env((char_u *)"~/", NameBuff, MAXPATHL);
        vim_strncpy(NameBuff + len, fm->fname + 2, MAXPATHL - len - 1);
     }
     else
diff --git a/src/misc1.c b/src/misc1.c
index 142a6161e..4571ff27f 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -1401,16 +1401,16 @@ expand_env_save_opt(char_u *src, int one)
  * Skips over "\ ", "\~" and "\$" (not for Win32 though).
  * If anything fails no expansion is done and dst equals src.
  */
-    void
+    size_t
 expand_env(
     char_u     *src,           // input string e.g. "$HOME/vim.hlp"
     char_u     *dst,           // where to put the result
     int                dstlen)         // maximum length of the result
 {
-    expand_env_esc(src, dst, dstlen, FALSE, FALSE, NULL);
+    return expand_env_esc(src, dst, dstlen, FALSE, FALSE, NULL);
 }
 
-    void
+    size_t
 expand_env_esc(
     char_u     *srcp,          // input string e.g. "$HOME/vim.hlp"
     char_u     *dst,           // where to put the result
@@ -1427,6 +1427,7 @@ expand_env_esc(
     int                mustfree;       // var was allocated, need to free it 
later
     int                at_start = TRUE; // at start of a name
     int                startstr_len = 0;
+    char_u     *dst_start = dst;
 
     if (startstr != NULL)
        startstr_len = (int)STRLEN(startstr);
@@ -1577,6 +1578,7 @@ expand_env_esc(
                 */
                {
                    char_u      test[MAXPATHL], paths[MAXPATHL];
+                   size_t      testlen;
                    char_u      *path, *next_path, *ptr;
                    stat_T      st;
 
@@ -1588,14 +1590,20 @@ expand_env_esc(
                                next_path++);
                        if (*next_path)
                            *next_path++ = NUL;
-                       STRCPY(test, path);
-                       STRCAT(test, "/");
-                       STRCAT(test, dst + 1);
+                       testlen = vim_snprintf_safelen(
+                           (char *)test,
+                           sizeof(test),
+                           "%s/%s",
+                           path,
+                           dst + 1);
                        if (mch_stat(test, &st) == 0)
                        {
-                           var = alloc(STRLEN(test) + 1);
-                           STRCPY(var, test);
-                           mustfree = TRUE;
+                           var = alloc(testlen + 1);
+                           if (var != NULL)
+                           {
+                               STRCPY(var, test);
+                               mustfree = TRUE;
+                           }
                            break;
                        }
                    }
@@ -1641,23 +1649,26 @@ expand_env_esc(
                }
            }
 
-           if (var != NULL && *var != NUL
-                   && (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen))
+           if (var != NULL && *var != NUL)
            {
-               STRCPY(dst, var);
-               dstlen -= (int)STRLEN(var);
                c = (int)STRLEN(var);
-               // if var[] ends in a path separator and tail[] starts
-               // with it, skip a character
-               if (after_pathsep(dst, dst + c)
+
+               if (c + STRLEN(tail) + 1 < (unsigned)dstlen)
+               {
+                   STRCPY(dst, var);
+                   dstlen -= c;
+                   // if var[] ends in a path separator and tail[] starts
+                   // with it, skip a character
+                   if (after_pathsep(dst, dst + c)
 #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA)
-                       && dst[c - 1] != ':'
+                           && dst[c - 1] != ':'
 #endif
-                       && vim_ispathsep(*tail))
-                   ++tail;
-               dst += c;
-               src = tail;
-               copy_char = FALSE;
+                           && vim_ispathsep(*tail))
+                       ++tail;
+                   dst += c;
+                   src = tail;
+                   copy_char = FALSE;
+               }
            }
            if (mustfree)
                vim_free(var);
@@ -1692,6 +1703,8 @@ expand_env_esc(
 
     }
     *dst = NUL;
+
+    return (size_t)(dst - dst_start);
 }
 
 /*
diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro
index 1a053e3db..d7c187af6 100644
--- a/src/proto/misc1.pro
+++ b/src/proto/misc1.pro
@@ -29,8 +29,8 @@ void free_users(void);
 void init_vimdir(void);
 char_u *expand_env_save(char_u *src);
 char_u *expand_env_save_opt(char_u *src, int one);
-void expand_env(char_u *src, char_u *dst, int dstlen);
-void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, int esc, int one, 
char_u *startstr);
+size_t expand_env(char_u *src, char_u *dst, int dstlen);
+size_t expand_env_esc(char_u *srcp, char_u *dst, int dstlen, int esc, int one, 
char_u *startstr);
 char_u *vim_getenv(char_u *name, int *mustfree);
 void vim_unsetenv(char_u *var);
 void vim_unsetenv_ext(char_u *var);
diff --git a/src/version.c b/src/version.c
index 0b6a3b028..168ff4e67 100644
--- a/src/version.c
+++ b/src/version.c
@@ -709,6 +709,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1467,
 /**/
     1466,
 /**/
diff --git a/src/viminfo.c b/src/viminfo.c
index 5e4caf81c..489cb2db0 100644
--- a/src/viminfo.c
+++ b/src/viminfo.c
@@ -99,6 +99,8 @@ viminfo_filename(char_u *file)
 {
     if (file == NULL || *file == NUL)
     {
+       size_t  len;
+
        if (*p_viminfofile != NUL)
            file = p_viminfofile;
        else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
@@ -127,9 +129,12 @@ viminfo_filename(char_u *file)
 #endif
                file = (char_u *)VIMINFO_FILE;
        }
-       expand_env(file, NameBuff, MAXPATHL);
+       len = expand_env(file, NameBuff, MAXPATHL);
        file = NameBuff;
+
+       return vim_strnsave(file, len);
     }
+
     return vim_strsave(file);
 }
 

-- 
-- 
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/E1uRvfo-006JOU-92%40256bit.org.

Raspunde prin e-mail lui