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 <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
John Marriott
2025-06-18 18:15:31 +02:00
committed by Christian Brabandt
parent 8311e7d6b4
commit fff0132399
8 changed files with 55 additions and 40 deletions

View File

@ -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);
}
/*