mirror of
https://github.com/neovim/neovim
synced 2025-07-16 01:01:49 +00:00
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:
@ -1449,11 +1449,10 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
|
|||||||
// copy file name into NameBuff, expanding environment variables
|
// copy file name into NameBuff, expanding environment variables
|
||||||
char save_char = ptr[len];
|
char save_char = ptr[len];
|
||||||
ptr[len] = NUL;
|
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;
|
ptr[len] = save_char;
|
||||||
|
|
||||||
xfree(*file_to_find);
|
xfree(*file_to_find);
|
||||||
file_to_findlen = strlen(NameBuff);
|
|
||||||
*file_to_find = xmemdupz(NameBuff, file_to_findlen);
|
*file_to_find = xmemdupz(NameBuff, file_to_findlen);
|
||||||
if (options & FNAME_UNESC) {
|
if (options & FNAME_UNESC) {
|
||||||
// Change all "\ " to " ".
|
// Change all "\ " to " ".
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "nvim/os/fs_defs.h"
|
#include "nvim/os/fs_defs.h"
|
||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
|
#include "nvim/os/os_defs.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
#include "nvim/pos_defs.h"
|
#include "nvim/pos_defs.h"
|
||||||
@ -3275,7 +3276,7 @@ static void vim_mktempdir(void)
|
|||||||
mode_t umask_save = umask(0077);
|
mode_t umask_save = umask(0077);
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); i++) {
|
for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); i++) {
|
||||||
// Expand environment variables, leave room for "/tmp/nvim.<user>/XXXXXX/999999999".
|
// 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 (!os_isdir(tmp)) {
|
||||||
if (strequal("$TMPDIR", temp_dirs[i])) {
|
if (strequal("$TMPDIR", temp_dirs[i])) {
|
||||||
if (!os_env_exists("TMPDIR", true)) {
|
if (!os_env_exists("TMPDIR", true)) {
|
||||||
@ -3288,9 +3289,13 @@ static void vim_mktempdir(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
|
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
|
||||||
add_pathsep(tmp);
|
if (!after_pathsep(tmp, tmp + tmplen)) {
|
||||||
xstrlcat(tmp, "nvim.", sizeof(tmp));
|
tmplen += (size_t)vim_snprintf(tmp + tmplen, sizeof(tmp) - tmplen, PATHSEPSTR);
|
||||||
xstrlcat(tmp, user, sizeof(tmp));
|
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.
|
os_mkdir(tmp, 0700); // Always create, to avoid a race.
|
||||||
bool owned = os_file_owned(tmp);
|
bool owned = os_file_owned(tmp);
|
||||||
bool isdir = os_isdir(tmp);
|
bool isdir = os_isdir(tmp);
|
||||||
@ -3301,7 +3306,10 @@ static void vim_mktempdir(void)
|
|||||||
bool valid = isdir && owned; // TODO(justinmk): Windows ACL?
|
bool valid = isdir && owned; // TODO(justinmk): Windows ACL?
|
||||||
#endif
|
#endif
|
||||||
if (valid) {
|
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 {
|
} else {
|
||||||
if (!owned) {
|
if (!owned) {
|
||||||
ELOG("tempdir root not owned by current user (%s): %s", user, tmp);
|
ELOG("tempdir root not owned by current user (%s): %s", user, tmp);
|
||||||
@ -3315,11 +3323,15 @@ static void vim_mktempdir(void)
|
|||||||
#endif
|
#endif
|
||||||
// If our "root" tempdir is invalid or fails, proceed without "<user>/".
|
// If our "root" tempdir is invalid or fails, proceed without "<user>/".
|
||||||
// Else user1 could break user2 by creating "/tmp/nvim.user2/".
|
// 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".
|
// 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);
|
int r = os_mkdtemp(tmp, path);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
WLOG("tempdir create failed: %s: %s", os_strerror(r), tmp);
|
WLOG("tempdir create failed: %s: %s", os_strerror(r), tmp);
|
||||||
|
@ -722,10 +722,8 @@ static void fname2fnum(xfmark_T *fm)
|
|||||||
#else
|
#else
|
||||||
if (fm->fname[0] == '~' && (fm->fname[1] == '/')) {
|
if (fm->fname[0] == '~' && (fm->fname[1] == '/')) {
|
||||||
#endif
|
#endif
|
||||||
|
size_t len = expand_env("~/", NameBuff, MAXPATHL);
|
||||||
expand_env("~/", NameBuff, MAXPATHL);
|
xstrlcpy(NameBuff + len, fm->fname + 2, MAXPATHL - len);
|
||||||
int len = (int)strlen(NameBuff);
|
|
||||||
xstrlcpy(NameBuff + len, fm->fname + 2, (size_t)(MAXPATHL - len));
|
|
||||||
} else {
|
} else {
|
||||||
xstrlcpy(NameBuff, fm->fname, MAXPATHL);
|
xstrlcpy(NameBuff, fm->fname, MAXPATHL);
|
||||||
}
|
}
|
||||||
|
@ -577,9 +577,9 @@ char *expand_env_save_opt(char *src, bool one)
|
|||||||
/// @param src Input string e.g. "$HOME/vim.hlp"
|
/// @param src Input string e.g. "$HOME/vim.hlp"
|
||||||
/// @param dst[out] Where to put the result
|
/// @param dst[out] Where to put the result
|
||||||
/// @param dstlen Maximum length of the result
|
/// @param dstlen Maximum length of the result
|
||||||
void expand_env(char *src, char *dst, int dstlen)
|
size_t expand_env(char *src, char *dst, int dstlen)
|
||||||
{
|
{
|
||||||
expand_env_esc(src, dst, dstlen, false, false, NULL);
|
return expand_env_esc(src, dst, dstlen, false, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand environment variable with path name and escaping.
|
/// Expand environment variable with path name and escaping.
|
||||||
@ -591,8 +591,8 @@ void expand_env(char *src, char *dst, int dstlen)
|
|||||||
/// @param esc Escape spaces in expanded variables
|
/// @param esc Escape spaces in expanded variables
|
||||||
/// @param one `srcp` is a single filename
|
/// @param one `srcp` is a single filename
|
||||||
/// @param prefix Start again after this (can be NULL)
|
/// @param prefix Start again after this (can be NULL)
|
||||||
void expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen, bool esc, bool one,
|
size_t expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen, bool esc, bool one,
|
||||||
char *prefix)
|
char *prefix)
|
||||||
FUNC_ATTR_NONNULL_ARG(1, 2)
|
FUNC_ATTR_NONNULL_ARG(1, 2)
|
||||||
{
|
{
|
||||||
char *tail;
|
char *tail;
|
||||||
@ -600,6 +600,7 @@ void expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen, b
|
|||||||
bool copy_char;
|
bool copy_char;
|
||||||
bool mustfree; // var was allocated, need to free it later
|
bool mustfree; // var was allocated, need to free it later
|
||||||
bool at_start = true; // at start of a name
|
bool at_start = true; // at start of a name
|
||||||
|
char *const dst_start = dst;
|
||||||
|
|
||||||
int prefix_len = (prefix == NULL) ? 0 : (int)strlen(prefix);
|
int prefix_len = (prefix == NULL) ? 0 : (int)strlen(prefix);
|
||||||
|
|
||||||
@ -731,23 +732,24 @@ void expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen, b
|
|||||||
mustfree = true;
|
mustfree = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var != NULL && *var != NUL
|
if (var != NULL && *var != NUL) {
|
||||||
&& (strlen(var) + strlen(tail) + 1 < (unsigned)dstlen)) {
|
|
||||||
STRCPY(dst, var);
|
|
||||||
dstlen -= (int)strlen(var);
|
|
||||||
int c = (int)strlen(var);
|
int c = (int)strlen(var);
|
||||||
// if var[] ends in a path separator and tail[] starts
|
if ((size_t)c + strlen(tail) + 1 < (unsigned)dstlen) {
|
||||||
// with it, skip a character
|
STRCPY(dst, var);
|
||||||
if (after_pathsep(dst, dst + c)
|
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)
|
#if defined(BACKSLASH_IN_FILENAME)
|
||||||
&& dst[c - 1] != ':'
|
&& dst[c - 1] != ':'
|
||||||
#endif
|
#endif
|
||||||
&& vim_ispathsep(*tail)) {
|
&& vim_ispathsep(*tail)) {
|
||||||
tail++;
|
tail++;
|
||||||
|
}
|
||||||
|
dst += c;
|
||||||
|
src = tail;
|
||||||
|
copy_char = false;
|
||||||
}
|
}
|
||||||
dst += c;
|
|
||||||
src = tail;
|
|
||||||
copy_char = false;
|
|
||||||
}
|
}
|
||||||
if (mustfree) {
|
if (mustfree) {
|
||||||
xfree(var);
|
xfree(var);
|
||||||
@ -778,6 +780,8 @@ void expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen, b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*dst = NUL;
|
*dst = NUL;
|
||||||
|
|
||||||
|
return (size_t)(dst - dst_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the directory "vimdir/<version>" or "vimdir/runtime" exists.
|
/// Check if the directory "vimdir/<version>" or "vimdir/runtime" exists.
|
||||||
|
@ -1314,8 +1314,9 @@ static char *shada_filename(const char *file)
|
|||||||
// because various expansions must have already be done by the shell.
|
// because various expansions must have already be done by the shell.
|
||||||
// If shell is not performing them then they should be done in main.c
|
// If shell is not performing them then they should be done in main.c
|
||||||
// where arguments are parsed, *not here*.
|
// where arguments are parsed, *not here*.
|
||||||
expand_env((char *)file, &(NameBuff[0]), MAXPATHL);
|
size_t len = expand_env((char *)file, &(NameBuff[0]), MAXPATHL);
|
||||||
file = &(NameBuff[0]);
|
file = &(NameBuff[0]);
|
||||||
|
return xmemdupz(file, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return xstrdup(file);
|
return xstrdup(file);
|
||||||
|
Reference in New Issue
Block a user