Subject: bin/28382: vi crashes when auto-completing long filenames
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <Peter.Bex@student.kun.nl>
List: netbsd-bugs
Date: 11/21/2004 21:58:00
>Number:         28382
>Category:       bin
>Synopsis:       When completing filenames longer than the screen is wide, vi segfaults
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 21 21:58:00 +0000 2004
>Originator:     Peter Bex
>Release:        NetBSD 2.0_BETA
>Organization:
	
>Environment:
	
	
System: NetBSD byers.nvie.com 2.0_BETA NetBSD 2.0_BETA (BYERS) #7: Thu Sep 2 12:51:54 CEST 2004 sjamaan@byers.nvie.com:/usr/src/sys/arch/macppc/compile/BYERS macppc
Architecture: powerpc
Machine: macppc
>Description:
	When you enable filecompletion, when a filename contains more
	characters than the screen is wide, vi crashes with a SEGFAULT.

	After code inspection, it appears on line 2237 of vi/v_txt.c,
	av[0]->bp is passed to msg_print.  av is not re-initialised after
	the last use of it in the loop which determines `colwidth'.
	At this point, av points beyond the last valid argv, which contains
	all NULL data.

	Looking at the `else' branch of the `if' in which the offending code
	is located, it appears the msg_print statement should simply be
	moved to the inside of the for loop.
>How-To-Repeat:
	- Create a file which has more characters than your screen is wide
	    or just resize your screen/terminal enough.
	- :set filec=^V^V^I
	- :e path/to/file/^I
	- See vi crash and burn ;)
>Fix:

This is a quick fix I hacked together.  Should do the trick.
(I'll send a copy of this message to Keith Bostic as well, so he can
 integrate the patch in nvi main distribution)

$NetBSD$

--- v_txt.c.orig	2003-06-06 10:06:47.000000000 +0200
+++ v_txt.c
@@ -2234,8 +2234,8 @@ txt_fc_col(sp, argc, argv)
 
 	/* If the largest file name is too large, just print them. */
 	if (colwidth > sp->cols) {
-		p = msg_print(sp, av[0]->bp + prefix, &nf);
 		for (ac = argc, av = argv; ac > 0; --ac, ++av) {
+			p = msg_print(sp, av[0]->bp + prefix, &nf);
 			(void)ex_printf(sp, "%s\n", p);
 			if (F_ISSET(gp, G_INTERRUPTED))
 				break;

>Unformatted: