> Delivered-To: marty...@venck.us
> Received: by 10.100.125.2 with SMTP id x2cs7548anc;
>         Wed, 8 Dec 2010 00:00:53 -0800 (PST)
> Received: by 10.231.32.197 with SMTP id e5mr738073ibd.188.1291795252925;
>         Wed, 08 Dec 2010 00:00:52 -0800 (PST)
> Return-Path: <owner-tech+m22...@openbsd.org>
> Received: from shear.ucar.edu (lists.openbsd.org [192.43.244.163])
>         by mx.google.com with ESMTP id 
> gy42si1064435ibb.88.2010.12.08.00.00.52;
>         Wed, 08 Dec 2010 00:00:52 -0800 (PST)
> Received-SPF: pass (google.com: manual fallback record for domain of 
> owner-tech+m22...@openbsd.org designates 192.43.244.163 as permitted sender) 
> client-ip=192.43.244.163;
> Authentication-Results: mx.google.com; spf=pass (google.com: manual fallback 
> record for domain of owner-tech+m22...@openbsd.org designates 192.43.244.163 
> as permitted sender) smtp.mail=owner-tech+m22...@openbsd.org
> Received: from openbsd.org (localhost.ucar.edu [127.0.0.1])
>       by shear.ucar.edu (8.14.3/8.14.3) with ESMTP id oB87xxwI017467;
>       Wed, 8 Dec 2010 00:59:59 -0700 (MST)
> Received: from mail.boxsoft.com (dsl092-062-211.lax1.dsl.speakeasy.net 
> [66.92.62.211])
>       by shear.ucar.edu (8.14.3/8.14.3) with ESMTP id oB87we7E023081 
> (version=TLSv1/SSLv3 cipher=DHE-DSS-AES256-SHA bits=256 verify=NO)
>       for <tech@openbsd.org>; Wed, 8 Dec 2010 00:58:42 -0700 (MST)
> Received: from mail.boxsoft.com (sidster@localhost [127.0.0.1])
>       by mail.boxsoft.com (8.14.3/8.14.3) with ESMTP id oB87weGu028472
>       for <tech@openbsd.org>; Tue, 7 Dec 2010 23:58:40 -0800 (PST)
> Received: (from sidster@localhost)
>       by mail.boxsoft.com (8.14.3/8.14.3/Submit) id oB87wdB5002430
>       for tech@openbsd.org; Tue, 7 Dec 2010 23:58:40 -0800 (PST)
> X-Authentication-Warning: roppongi.boxsoft.com: sidster set sender to 
> sids...@boxsoft.com using -f
> Date: Tue, 7 Dec 2010 23:58:39 -0800
> From: patrick keshishian <sids...@boxsoft.com>
> To: tech@openbsd.org
> Subject: nvi diff fixing a display glitch leading to crash
> Message-ID: <20101208075839.gc2...@roppongi.boxsoft.com>
> Mime-Version: 1.0
> Content-Type: text/plain; charset=us-ascii
> User-Agent: Mutt/1.4.2.3i
> List-Help: <mailto:majord...@openbsd.org?body=help>
> List-Owner: <mailto:tech-ow...@openbsd.org>
> List-Post: <mailto:tech@openbsd.org>
> List-Subscribe: <mailto:majord...@openbsd.org?body=sub%20tech>
> List-Unsubscribe: <mailto:majord...@openbsd.org?body=unsub%20tech>
> X-Loop: tech@openbsd.org
> Precedence: list
> Sender: owner-t...@openbsd.org
>
> Hello,
>
> I work with a lot of sources that have strange formatting
> (as do you no doubt). I noticed that sometimes changing the
> tabstop value in search of a reasonable display vi would
> crash.
>
> Took me a bit to figure out the reproducible steps to be
> able to come up with a fix.
>
> Steps to reproduce the crash. Reproducible on i386, amd64,
> and macppc:
>
> 1. Imagine a file edited with a small tabstop value (say 2
>    or 3) containing lines long enough so they wrap in default
>    tabstop (8), but possibly not in the smaller tabstop values.
>
> 2. While tabstop set to 8, position one of the wrapping lines
>    such that the beginning of said line is off screen and the
>    tail end of the wrapped portion is the first line on the
>    screen with the cursor positioned on same first line.
>
> 3. Change tabstop to 2 (or 3).
>    Assuming there were more lines below the line your cursor
>    is on, you will notice a drawing glitch where only the
>    top line is redrawn and the rest of the screen is blanked
>    out.
>
> 4. If at this point you press ^B (page backwards) vi will
>    core dump.
>
> A visual of what I experience (series of five screen-shots):
>       http://sidster.com/scratch/nvi/
>
>
> The patch below resets the HMAP->soff (screen offset of line)
> to 1 if the number of lines HMAP->lno spans has changed and is
> now less than HMAP->soff. This essentially forces the entire
> line to be redrawn at the top of the screen, avoids the redraw
> glitch and eventual crash.
>
> Comments?

Thanks for the detailed report.

However, your diff is wrong.

> --patrick
>
>
> Index: vi/vs_smap.c
> ===================================================================
> RCS file: /cvs/obsd/src/usr.bin/vi/vi/vs_smap.c,v
> retrieving revision 1.7
> diff -u -p vi/vs_smap.c
> --- vi/vs_smap.c      27 Oct 2009 23:59:49 -0000      1.7
> +++ vi/vs_smap.c      8 Dec 2010 06:22:09 -0000
> @@ -224,6 +224,17 @@ top:                     HMAP->lno = lno;
>                       HMAP->coff = 0;
>                       HMAP->soff = 1;
>               }
> +             else {

This is not the right place to fix this, since it would affect the
other 6 calls with OOBLNO in a bad way.

> +                     /*
> +                      * If number of lines HMAP->lno (top line) spans
> +                      * changed due to, say reformatting, and now is
> +                      * fewer than HMAP->soff, reset so the line is
> +                      * redrawn at the top of the screen.
> +                      */

This should additionally check if the current line is HMAP->lno
(top line);  otherwise you're changing behaviour in a strange way,
the top line will be forced to be on top.  (Try it.)

> +                     cnt = vs_screens(sp, HMAP->lno, NULL);

This could use the cached value (cno), it would be faster for larger
lines.

> +                     if (cnt < HMAP->soff)
> +                             HMAP->soff = 1;

This should actually be cnt, not 1--you're forcing the top to be
at the beginning of the line;  however this is only good for your
test case (two lines become one).  This is bad for longer lines.

> +             }

A similar problem applies for the TMAP case, too.

>               /* If we fail, just punt. */
>               for (p = HMAP, cnt = sp->t_rows; --cnt; ++p)
>                       if (vs_sm_next(sp, p, p + 1))

Could you verify that the attached diff fixes your problem?

Index: vi/vs_refresh.c
===================================================================
RCS file: /cvs/src/usr.bin/vi/vi/vs_refresh.c,v
retrieving revision 1.16
diff -u -r1.16 vs_refresh.c
--- vi/vs_refresh.c     27 Oct 2009 23:59:49 -0000      1.16
+++ vi/vs_refresh.c     3 Apr 2011 10:13:47 -0000
@@ -199,9 +199,18 @@
                else if (F_ISSET(sp, SC_SCR_CENTER)) {
                        if (vs_sm_fill(sp, LNO, P_MIDDLE))
                                return (1);
-               } else
+               } else {
+                       if (LNO == HMAP->lno || LNO == TMAP->lno) {
+                               cnt = vs_screens(sp, LNO, &CNO);
+                               if (LNO == HMAP->lno && cnt < HMAP->soff)
+                                       HMAP->soff = cnt;
+                               if (LNO == TMAP->lno && cnt > TMAP->soff)
+                                       TMAP->soff = cnt;
+                       }
+
                        if (vs_sm_fill(sp, OOBLNO, P_TOP))
                                return (1);
+               }
                F_SET(sp, SC_SCR_REDRAW);
        }

Reply via email to