vim-patch:9.1.1467: too many strlen() calls (#34572)

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: vim/vim#17561

fff0132399

Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
zeertzjq
2025-06-19 10:21:33 +08:00
committed by GitHub
parent 8ed6f00ab0
commit fb8dba413f
5 changed files with 45 additions and 31 deletions

View File

@@ -58,6 +58,7 @@
#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
@@ -3275,7 +3276,7 @@ static void vim_mktempdir(void)
mode_t umask_save = umask(0077);
for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); i++) {
// Expand environment variables, leave room for "/tmp/nvim.<user>/XXXXXX/999999999".
expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
size_t tmplen = expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
if (!os_isdir(tmp)) {
if (strequal("$TMPDIR", temp_dirs[i])) {
if (!os_env_exists("TMPDIR", true)) {
@@ -3288,9 +3289,13 @@ static void vim_mktempdir(void)
}
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
add_pathsep(tmp);
xstrlcat(tmp, "nvim.", sizeof(tmp));
xstrlcat(tmp, user, sizeof(tmp));
if (!after_pathsep(tmp, tmp + tmplen)) {
tmplen += (size_t)vim_snprintf(tmp + tmplen, sizeof(tmp) - tmplen, PATHSEPSTR);
assert(tmplen < sizeof(tmp));
}
tmplen += (size_t)vim_snprintf(tmp + tmplen, sizeof(tmp) - tmplen,
"nvim.%s", user);
assert(tmplen < sizeof(tmp));
os_mkdir(tmp, 0700); // Always create, to avoid a race.
bool owned = os_file_owned(tmp);
bool isdir = os_isdir(tmp);
@@ -3301,7 +3306,10 @@ static void vim_mktempdir(void)
bool valid = isdir && owned; // TODO(justinmk): Windows ACL?
#endif
if (valid) {
add_pathsep(tmp);
if (!after_pathsep(tmp, tmp + tmplen)) {
tmplen += (size_t)vim_snprintf(tmp + tmplen, sizeof(tmp) - tmplen, PATHSEPSTR);
assert(tmplen < sizeof(tmp));
}
} else {
if (!owned) {
ELOG("tempdir root not owned by current user (%s): %s", user, tmp);
@@ -3315,11 +3323,15 @@ static void vim_mktempdir(void)
#endif
// If our "root" tempdir is invalid or fails, proceed without "<user>/".
// Else user1 could break user2 by creating "/tmp/nvim.user2/".
tmp[strlen(tmp) - strlen(user)] = NUL;
tmplen -= strlen(user);
tmp[tmplen] = NUL;
}
// Now try to create "/tmp/nvim.<user>/XXXXXX".
xstrlcat(tmp, "XXXXXX", sizeof(tmp)); // mkdtemp "template", will be replaced with random alphanumeric chars.
// "XXXXXX" is mkdtemp "template", will be replaced with random alphanumeric chars.
tmplen += (size_t)vim_snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "XXXXXX");
assert(tmplen < sizeof(tmp));
(void)tmplen;
int r = os_mkdtemp(tmp, path);
if (r != 0) {
WLOG("tempdir create failed: %s: %s", os_strerror(r), tmp);