patch 9.1.1515: Coverity complains about potential unterminated strings

Problem:    memcpy() in ExpandRTDir_int() may create unterminated strings
Solution:   Use vim_snprintf() to construct complete paths safely
            (glepnir).

related: neovim/neovim#34795
closes: #17669

Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
glepnir
2025-07-06 11:02:51 +02:00
committed by Christian Brabandt
parent b7b4bb36aa
commit 21449ee49c
2 changed files with 28 additions and 14 deletions

View File

@ -1128,43 +1128,51 @@ ExpandRTDir_int(
{
for (int i = 0; dirnames[i] != NULL; ++i)
{
size_t buf_len = STRLEN(dirnames[i]) + pat_len + 22;
const size_t buf_len = STRLEN(dirnames[i]) + pat_len + 64;
char *buf = alloc(buf_len);
if (buf == NULL)
{
ga_clear_strings(gap);
return;
}
char *tail = buf + 15;
size_t tail_buflen = buf_len - 15;
int glob_flags = 0;
int expand_dirs = FALSE;
if (*(dirnames[i]) == NUL) // empty dir used for :runtime
vim_snprintf(tail, tail_buflen, "%s*.vim", pat);
else
vim_snprintf(tail, tail_buflen, "%s/%s*.vim", dirnames[i], pat);
// Build base pattern
vim_snprintf(buf, buf_len, "%s%s%s%s",
*dirnames[i] ? dirnames[i] : "", *dirnames[i] ? "/" : "",
pat, "*.vim");
expand:
if ((flags & DIP_NORTP) == 0)
globpath(p_rtp, (char_u *)tail, gap, glob_flags, expand_dirs);
globpath(p_rtp, (char_u *)buf, gap, glob_flags, expand_dirs);
if (flags & DIP_START)
{
memcpy(tail - 15, "pack/*/start/*/", 15);
globpath(p_pp, (char_u *)tail - 15, gap, glob_flags, expand_dirs);
// Build complete search path: pack/*/start/*/dirnames[i]/pat*.vim
vim_snprintf(buf, buf_len, "pack/*/start/*/%s%s%s%s",
*dirnames[i] ? dirnames[i] : "",
*dirnames[i] ? "/" : "",
pat,
expand_dirs ? "*" : "*.vim");
globpath(p_pp, (char_u *)buf, gap, glob_flags, expand_dirs);
}
if (flags & DIP_OPT)
{
memcpy(tail - 13, "pack/*/opt/*/", 13);
globpath(p_pp, (char_u *)tail - 13, gap, glob_flags, expand_dirs);
// Build complete search path: pack/*/opt/*/dirnames[i]/pat*.vim
vim_snprintf(buf, buf_len, "pack/*/opt/*/%s%s%s%s",
*dirnames[i] ? dirnames[i] : "",
*dirnames[i] ? "/" : "", pat,
expand_dirs ? "*" : "*.vim");
globpath(p_pp, (char_u *)buf, gap, glob_flags, expand_dirs);
}
if (*(dirnames[i]) == NUL && !expand_dirs)
// Second round for directories
if (*dirnames[i] == NUL && !expand_dirs)
{
// expand dir names in another round
vim_snprintf(tail, tail_buflen, "%s*", pat);
vim_snprintf(buf, buf_len, "%s*", pat);
glob_flags = WILD_ADD_SLASH;
expand_dirs = TRUE;
goto expand;
@ -1175,8 +1183,10 @@ expand:
int pat_pathsep_cnt = 0;
for (size_t i = 0; i < pat_len; ++i)
{
if (vim_ispathsep(pat[i]))
++pat_pathsep_cnt;
}
for (int i = 0; i < gap->ga_len; ++i)
{
@ -1191,9 +1201,11 @@ expand:
int match_pathsep_cnt = (e > s && e[-1] == '/') ? -1 : 0;
for (s = e; s > match; MB_PTR_BACK(match, s))
{
if (s < match || (vim_ispathsep(*s)
&& ++match_pathsep_cnt > pat_pathsep_cnt))
break;
}
++s;
if (s != match)
mch_memmove(match, s, e - s + 1);

View File

@ -719,6 +719,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1515,
/**/
1514,
/**/