0
0
mirror of https://github.com/vim/vim.git synced 2025-08-25 19:53:53 -04:00

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
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
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) 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); char *buf = alloc(buf_len);
if (buf == NULL) if (buf == NULL)
{ {
ga_clear_strings(gap); ga_clear_strings(gap);
return; return;
} }
char *tail = buf + 15;
size_t tail_buflen = buf_len - 15;
int glob_flags = 0; int glob_flags = 0;
int expand_dirs = FALSE; int expand_dirs = FALSE;
if (*(dirnames[i]) == NUL) // empty dir used for :runtime // Build base pattern
vim_snprintf(tail, tail_buflen, "%s*.vim", pat); vim_snprintf(buf, buf_len, "%s%s%s%s",
else *dirnames[i] ? dirnames[i] : "", *dirnames[i] ? "/" : "",
vim_snprintf(tail, tail_buflen, "%s/%s*.vim", dirnames[i], pat); pat, "*.vim");
expand: expand:
if ((flags & DIP_NORTP) == 0) 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) if (flags & DIP_START)
{ {
memcpy(tail - 15, "pack/*/start/*/", 15); // Build complete search path: pack/*/start/*/dirnames[i]/pat*.vim
globpath(p_pp, (char_u *)tail - 15, gap, glob_flags, expand_dirs); 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) if (flags & DIP_OPT)
{ {
memcpy(tail - 13, "pack/*/opt/*/", 13); // Build complete search path: pack/*/opt/*/dirnames[i]/pat*.vim
globpath(p_pp, (char_u *)tail - 13, gap, glob_flags, expand_dirs); 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 // 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; glob_flags = WILD_ADD_SLASH;
expand_dirs = TRUE; expand_dirs = TRUE;
goto expand; goto expand;
@ -1175,8 +1183,10 @@ expand:
int pat_pathsep_cnt = 0; int pat_pathsep_cnt = 0;
for (size_t i = 0; i < pat_len; ++i) for (size_t i = 0; i < pat_len; ++i)
{
if (vim_ispathsep(pat[i])) if (vim_ispathsep(pat[i]))
++pat_pathsep_cnt; ++pat_pathsep_cnt;
}
for (int i = 0; i < gap->ga_len; ++i) for (int i = 0; i < gap->ga_len; ++i)
{ {
@ -1191,9 +1201,11 @@ expand:
int match_pathsep_cnt = (e > s && e[-1] == '/') ? -1 : 0; int match_pathsep_cnt = (e > s && e[-1] == '/') ? -1 : 0;
for (s = e; s > match; MB_PTR_BACK(match, s)) for (s = e; s > match; MB_PTR_BACK(match, s))
{
if (s < match || (vim_ispathsep(*s) if (s < match || (vim_ispathsep(*s)
&& ++match_pathsep_cnt > pat_pathsep_cnt)) && ++match_pathsep_cnt > pat_pathsep_cnt))
break; break;
}
++s; ++s;
if (s != match) if (s != match)
mch_memmove(match, s, e - s + 1); mch_memmove(match, s, e - s + 1);

View File

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