UPDATE

On Sat, Apr 18, 2026 at 09:13:49AM +0200, Walter Alejandro Iglesias wrote:
> I'm not posting this on tech@ because, besides the upcoming release,
> I'm still not fully convinced with the explanations and solutions (diffs
> below) I've come to so far with this bug:
> 
>   https://marc.info/?l=openbsd-tech&m=176956435717456&w=2
> 
> Perhaps those who hacked vi(1) in the past can lend me a hand.  First of
> all, a concise explanation:
> 
> vi(1) crashes when quitting from a temporary buffer in visual mode while
> running global from ex(1).  Steps to reproduce:
> 
>   $ printf 'foo\nfoo\nfoo\n' > foo
>   $ ex foo
>   foo: unmodified: line 3
>   :g/foo/vi
>   :q
>   :q
>   ex(33568) in free(): write to free mem 0xd2bda37b780[0..7]@192
>   Abort trap (core dumped)
> 


With the other diff I posted for this issue the segfault still happened
in some scenarios, plus some regressions.  With this one, I haven't had
any problem so far:


Index: common/exf.c
===================================================================
RCS file: /cvs/src/usr.bin/vi/common/exf.c,v
diff -u -p -u -p -r1.50 exf.c
--- common/exf.c        15 Feb 2024 00:55:01 -0000      1.50
+++ common/exf.c        20 Apr 2026 08:00:52 -0000
@@ -407,7 +407,8 @@ file_init(SCR *sp, FREF *frp, char *rcv_
                O_CLR(sp, O_READONLY);
 
        /* Switch... */
-       ++ep->refcnt;
+       if (!F_ISSET(sp, SC_EX_GLOBAL))
+               ++ep->refcnt;
        sp->ep = ep;
        sp->frp = frp;
 



Load again *ecp, but only when it won't change the command currently
processed:


Index: ex/ex.c
===================================================================
RCS file: /cvs/src/usr.bin/vi/ex/ex.c,v
diff -u -p -u -p -r1.23 ex.c
--- ex/ex.c     23 Jun 2023 15:06:45 -0000      1.23
+++ ex/ex.c     19 Apr 2026 15:50:18 -0000
@@ -1374,6 +1374,9 @@ addr_verify:
                goto err;
        }
 
+       if (LIST_FIRST(&gp->ecq) == &gp->excmd)
+               ecp = &gp->excmd;
+
 #ifdef DEBUG
        /* Make sure no function left global temporary space locked. */
        if (F_ISSET(gp, G_TMP_INUSE)) {



-- 
Walter

Reply via email to