> Hmm. I get neither a seg fault nor a loop on my amd64 Lenove E595. The
> cursor moves to different spots in X/i3 xterm vs console and in either
> case doesn't do any replacement.

I can reproduce both behaviors reliably as follows both on console and
in xterm.

$ echo 'a\n\n\nb' > /tmp/test
$ mg /tmp/test

Don't move the cursor, just do the following (what is between quotation
marks is what you are supposed to type, the other bits are prompts):

"M-x query-replace-regexp<enter>"
RE Query replace: "^<enter>"
Query replace ^ with: "a<enter>"
Query replacing ^ with a: "<enter>"
<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit "!"

After hitting "!" here, it will enter a loop and eventually print

panic: Out of memory in undo code (record)

and exit.

If I do the exact same dance after moving the cursor to the second
(empty) line, it will segfault.

With the diff below (which is what I understood to be Hiltjo's
suggestion), I get more or less what I would expect. I think it should
not replace the empty line after the last newline...

So I think both diffs are not quite right :)

Index: line.c
===================================================================
RCS file: /var/cvs/src/usr.bin/mg/line.c,v
retrieving revision 1.61
diff -u -p -r1.61 line.c
--- line.c      29 Aug 2018 07:50:16 -0000      1.61
+++ line.c      21 Jul 2020 14:58:49 -0000
@@ -556,6 +556,8 @@ lreplace(RSIZE plen, char *st)
                goto done;
 
        lp = curwp->w_dotp;
+       if (ltext(lp) == NULL)
+               goto done;
        doto = curwp->w_doto;
        n = plen;
 
Index: re_search.c
===================================================================
RCS file: /var/cvs/src/usr.bin/mg/re_search.c,v
retrieving revision 1.34
diff -u -p -r1.34 re_search.c
--- re_search.c 9 Jul 2020 10:42:24 -0000       1.34
+++ re_search.c 21 Jul 2020 15:00:08 -0000
@@ -308,7 +308,7 @@ re_doreplace(RSIZE plen, char *st)
 static int
 re_forwsrch(void)
 {
-       int      tbo, tdotline, error;
+       int              re_flags, tbo, tdotline, error;
        struct line     *clp;
 
        clp = curwp->w_dotp;
@@ -330,10 +330,13 @@ re_forwsrch(void)
         * always makes the last line empty so this is good.
         */
        while (clp != (curbp->b_headp)) {
+               re_flags = REG_STARTEND;
+               if (tbo != 0)
+                       re_flags |= REG_NOTBOL;
                regex_match[0].rm_so = tbo;
                regex_match[0].rm_eo = llength(clp);
                error = regexec(&regex_buff, ltext(clp) ? ltext(clp) : "",
-                   RE_NMATCH, regex_match, REG_STARTEND);
+                   RE_NMATCH, regex_match, re_flags);
                if (error != 0) {
                        clp = lforw(clp);
                        tdotline++;

Reply via email to