]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1532: crash when expanding "~" in substitute causes very long text v9.0.1532
authorBram Moolenaar <Bram@vim.org>
Tue, 9 May 2023 20:15:30 +0000 (21:15 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 9 May 2023 20:15:30 +0000 (21:15 +0100)
Problem:    Crash when expanding "~" in substitute causes very long text.
Solution:   Limit the text length to MAXCOL.

src/regexp.c
src/testdir/test_substitute.vim
src/version.c

index 33b36d11a8be1a48c747c5b308feadeaee866bef..0e6c746df81975c55abc98708f200a93da7f01e6 100644 (file)
@@ -1767,10 +1767,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)
     {
@@ -1779,24 +1776,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)
index 7491b6163dc8260687853f4a24cb7f671236d447..32e2f2785479db402d3ef5fc67d14d7f9e740164 100644 (file)
@@ -1414,6 +1414,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()
index 7ee9f575f9bd90f04e8e3cfcac404a45fd8b5988..3fb73b25ea33732f47bb47d7439c882b877b3724 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1532,
 /**/
     1531,
 /**/