vim-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.

ab9a2d884b

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
zeertzjq 2023-11-17 06:55:08 +08:00
parent a388c852c4
commit d2f2e2725c
2 changed files with 36 additions and 17 deletions

View File

@ -1642,33 +1642,38 @@ static void do_lower(int *d, int c)
char *regtilde(char *source, int magic, bool preview)
{
char *newsub = source;
char *tmpsub;
char *p;
int len;
int prevlen;
for (p = newsub; *p; p++) {
for (char *p = newsub; *p; p++) {
if ((*p == '~' && magic) || (*p == '\\' && *(p + 1) == '~' && !magic)) {
if (reg_prev_sub != NULL) {
// length = len(newsub) - 1 + len(prev_sub) + 1
prevlen = (int)strlen(reg_prev_sub);
tmpsub = xmalloc(strlen(newsub) + (size_t)prevlen);
// Avoid making the text longer than MAXCOL, it will cause
// 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 *tmpsub = xmalloc(newsublen + prevsublen);
// copy prefix
len = (int)(p - newsub); // not including ~
memmove(tmpsub, newsub, (size_t)len);
size_t prefixlen = (size_t)(p - newsub); // not including ~
memmove(tmpsub, newsub, prefixlen);
// interpret tilde
memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen);
memmove(tmpsub + prefixlen, reg_prev_sub, prevsublen);
// copy postfix
if (!magic) {
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
xfree(newsub);
}
newsub = tmpsub;
p = newsub + len + prevlen;
p = newsub + prefixlen + prevsublen;
} else if (magic) {
STRMOVE(p, p + 1); // remove '~'
} else {

View File

@ -1415,6 +1415,20 @@ func Test_substitute_short_cmd()
bw!
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
" called to evaluate an expression but it is not used in a second call.
func Test_z_substitute_expr_leak()