98 lines
3.1 KiB
Diff
98 lines
3.1 KiB
Diff
From ab9a2d884b3a4abe319606ea95a5a6d6b01cd73a Mon Sep 17 00:00:00 2001
|
|
From: Bram Moolenaar <Bram@vim.org>
|
|
Date: Tue, 9 May 2023 21:15:30 +0100
|
|
Subject: [PATCH] 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.
|
|
---
|
|
src/regexp.c | 30 +++++++++++++++++++-----------
|
|
src/testdir/test_substitute.vim | 14 ++++++++++++++
|
|
2 files changed, 33 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/src/regexp.c b/src/regexp.c
|
|
index 33b36d11a8be..0e6c746df819 100644
|
|
--- a/src/regexp.c
|
|
+++ b/src/regexp.c
|
|
@@ -1723,10 +1723,7 @@ do_Lower(int *d, int c)
|
|
regtilde(char_u *source, int magic)
|
|
{
|
|
char_u *newsub = source;
|
|
- char_u *tmpsub;
|
|
char_u *p;
|
|
- int len;
|
|
- int prevlen;
|
|
|
|
for (p = newsub; *p; ++p)
|
|
{
|
|
@@ -1735,24 +1732,35 @@ regtilde(char_u *source, int magic)
|
|
if (reg_prev_sub != NULL)
|
|
{
|
|
// length = len(newsub) - 1 + len(prev_sub) + 1
|
|
- prevlen = (int)STRLEN(reg_prev_sub);
|
|
- tmpsub = alloc(STRLEN(newsub) + 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_u *tmpsub = alloc(newsublen + prevsublen);
|
|
if (tmpsub != NULL)
|
|
{
|
|
// copy prefix
|
|
- len = (int)(p - newsub); // not including ~
|
|
- mch_memmove(tmpsub, newsub, (size_t)len);
|
|
+ size_t prefixlen = p - newsub; // not including ~
|
|
+ mch_memmove(tmpsub, newsub, prefixlen);
|
|
// interpret tilde
|
|
- mch_memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen);
|
|
+ mch_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
|
|
vim_free(newsub);
|
|
newsub = tmpsub;
|
|
- p = newsub + len + prevlen;
|
|
+ p = newsub + prefixlen + prevsublen;
|
|
}
|
|
}
|
|
else if (magic)
|
|
diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim
|
|
index 7491b6163dc8..32e2f2785479 100644
|
|
--- a/src/testdir/test_substitute.vim
|
|
+++ b/src/testdir/test_substitute.vim
|
|
@@ -1394,6 +1394,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()
|