On Sun, Jan 19, 2014 at 9:57 PM, Bram Moolenaar <[email protected]> wrote:

>
> Christian Brabandt wrote:
>
> > On Mi, 15 Jan 2014, Aidan Marlin wrote:
> > > Vim devs,
> > >
> > > I have discovered a bug which affects at least 7.4.135 and (likely)
> 7.3.547. Example file is available at
> https://mega.co.nz/#!ndVjXZTY!aMX_9ll-0ce861tQwNZBaFveb_kONCJxvAT2GZOvzlc(1.2MB
>  in size) which will crash vim when attempting the following regex:
> > >
> > > :%s/\n//g
> > >
> > > The file contains 20 000 lines, each line containing 60 characters.
> > >
> > > Join (:%j) works fine and fast in these versions of vim, while the
> above regex seems to consume excessive amounts of memory, and results in
> vim crash.
> >
> > How about to alias :s/\n// to the join function (see attached patch).
>
> OK, but with a slightly different pattern it would still be a problem.
> Did you look at the cause of the problem?


":%s/\n//" process lines one by one.

1)
a   <save for undo
b
c

2)
ab  <replace
b
c

3)
ab
b   <save for undo
c

4)
ab
c   <delete

5)
ab  <save for undo
c

6)
abc <replace
c

7)
abc
c   <save for undo

8)
abc
    <delete

So, undo memory size is about m * (((n + 1) * n / 2) - 1), where n is
number of lines and m is line length.

Perhaps it might be possible to re-use undo entry even after insert or
delete lines when new change is done above it?

diff -r 89b3a7ef9622 src/undo.c
--- a/src/undo.c    Thu Jan 23 22:45:58 2014 +0100
+++ b/src/undo.c    Sun Jan 26 20:52:22 2014 +0900
@@ -565,16 +565,18 @@
             break;

         /* If lines have been inserted/deleted we give up.
-         * Also when the line was included in a multi-line save. */
-        if ((curbuf->b_u_newhead->uh_getbot_entry != uep
+         * Also when the line was included in a multi-line save.
+         * Except when new change is done above this entry. */
+        if (bot > uep->ue_top + 1
+            && ((curbuf->b_u_newhead->uh_getbot_entry != uep
                 ? (uep->ue_top + uep->ue_size + 1
                 != (uep->ue_bot == 0
                     ? curbuf->b_ml.ml_line_count + 1
                     : uep->ue_bot))
                 : uep->ue_lcount != curbuf->b_ml.ml_line_count)
-            || (uep->ue_size > 1
-                && top >= uep->ue_top
-                && top + 2 <= uep->ue_top + uep->ue_size + 1))
+                || (uep->ue_size > 1
+                && top >= uep->ue_top
+                && top + 2 <= uep->ue_top + uep->ue_size + 1)))
             break;

         /* If it's the same line we can skip saving it again. */


-- 
Yukihiro Nakadaira - [email protected]

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Raspunde prin e-mail lui