0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

patch 9.0.1532: crash when expanding "~" in substitute causes very long text

Problem:    Crash when expanding "~" in substitute causes very long text.
Solution:   Limit the text length to MAXCOL.
This commit is contained in:
Bram Moolenaar
2023-05-09 21:15:30 +01:00
parent d1ae8366af
commit ab9a2d884b
3 changed files with 35 additions and 11 deletions

View File

@@ -1767,10 +1767,7 @@ do_Lower(int *d, int c)
regtilde(char_u *source, int magic) regtilde(char_u *source, int magic)
{ {
char_u *newsub = source; char_u *newsub = source;
char_u *tmpsub;
char_u *p; char_u *p;
int len;
int prevlen;
for (p = newsub; *p; ++p) for (p = newsub; *p; ++p)
{ {
@@ -1779,24 +1776,35 @@ regtilde(char_u *source, int magic)
if (reg_prev_sub != NULL) if (reg_prev_sub != NULL)
{ {
// length = len(newsub) - 1 + len(prev_sub) + 1 // length = len(newsub) - 1 + len(prev_sub) + 1
prevlen = (int)STRLEN(reg_prev_sub); // Avoid making the text longer than MAXCOL, it will cause
tmpsub = alloc(STRLEN(newsub) + prevlen); // trouble at some point.
size_t prevsublen = STRLEN(reg_prev_sub);
size_t newsublen = STRLEN(newsub);
if (prevsublen > MAXCOL || newsublen > MAXCOL
|| newsublen + prevsublen > MAXCOL)
{
emsg(_(e_resulting_text_too_long));
break;
}
char_u *tmpsub = alloc(newsublen + prevsublen);
if (tmpsub != NULL) if (tmpsub != NULL)
{ {
// copy prefix // copy prefix
len = (int)(p - newsub); // not including ~ size_t prefixlen = p - newsub; // not including ~
mch_memmove(tmpsub, newsub, (size_t)len); mch_memmove(tmpsub, newsub, prefixlen);
// interpret tilde // interpret tilde
mch_memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen); mch_memmove(tmpsub + prefixlen, reg_prev_sub,
prevsublen);
// copy postfix // copy postfix
if (!magic) if (!magic)
++p; // back off backslash ++p; // back off backslash
STRCPY(tmpsub + len + prevlen, p + 1); STRCPY(tmpsub + prefixlen + prevsublen, p + 1);
if (newsub != source) // already allocated newsub if (newsub != source) // allocated newsub before
vim_free(newsub); vim_free(newsub);
newsub = tmpsub; newsub = tmpsub;
p = newsub + len + prevlen; p = newsub + prefixlen + prevsublen;
} }
} }
else if (magic) else if (magic)

View File

@@ -1414,6 +1414,20 @@ func Test_substitute_short_cmd()
bw! bw!
endfunc endfunc
" Check handling expanding "~" resulting in extremely long text.
func Test_substitute_tilde_too_long()
enew!
s/.*/ixxx
s//~~~~~~~~~AAAAAAA@(
" Either fails with "out of memory" or "text too long".
" This can take a long time.
call assert_fails('sil! norm &&&&&&&&&', ['E1240:\|E342:'])
bwipe!
endfunc
" This should be done last to reveal a memory leak when vim_regsub_both() is " This should be done last to reveal a memory leak when vim_regsub_both() is
" called to evaluate an expression but it is not used in a second call. " called to evaluate an expression but it is not used in a second call.
func Test_z_substitute_expr_leak() func Test_z_substitute_expr_leak()

View File

@@ -695,6 +695,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 */
/**/
1532,
/**/ /**/
1531, 1531,
/**/ /**/