Tue Jul 7 10:58:43 2020 UTC ()
PR bin/55468

Fix crash due to out-of-bounds access with Ctrl-W.

PR is only for nottywerase, but also fix ttywerase case, taken from
OpenBSD via nvi2:

http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/vi/vi/v_txt.c#rev1.23
https://github.com/lichray/nvi2/commit/5d5365d3585f45651f9b4a366391798a91393337

Also, comment there is no worry for altwerase specific code, which
seems suspicious at a glance.

Reported by Azuma OKAMOTO.
Thanks for detailed explanation how to reproduce the problem!


(rin)
diff -r1.6 -r1.7 src/external/bsd/nvi/dist/vi/v_txt.c

cvs diff -r1.6 -r1.7 src/external/bsd/nvi/dist/vi/v_txt.c (expand / switch to context diff)
--- src/external/bsd/nvi/dist/vi/v_txt.c 2018/08/07 08:05:47 1.6
+++ src/external/bsd/nvi/dist/vi/v_txt.c 2020/07/07 10:58:43 1.7
@@ -1,4 +1,4 @@
-/*	$NetBSD: v_txt.c,v 1.6 2018/08/07 08:05:47 rin Exp $ */
+/*	$NetBSD: v_txt.c,v 1.7 2020/07/07 10:58:43 rin Exp $ */
 /*-
  * Copyright (c) 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -16,7 +16,7 @@
 static const char sccsid[] = "Id: v_txt.c,v 10.108 2003/07/18 21:27:42 skimo Exp  (Berkeley) Date: 2003/07/18 21:27:42 ";
 #endif /* not lint */
 #else
-__RCSID("$NetBSD: v_txt.c,v 1.6 2018/08/07 08:05:47 rin Exp $");
+__RCSID("$NetBSD: v_txt.c,v 1.7 2020/07/07 10:58:43 rin Exp $");
 #endif
 
 #include <sys/types.h>
@@ -1118,32 +1118,30 @@
 		 */
 		if (LF_ISSET(TXT_TTYWERASE))
 			while (tp->cno > max) {
+				if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
+					break;
 				--tp->cno;
 				++tp->owrite;
 				if (FL_ISSET(is_flags, IS_RUNNING))
 					tp->lb[tp->cno] = ' ';
-				if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
-					break;
 			}
 		else {
 			if (LF_ISSET(TXT_ALTWERASE)) {
-				--tp->cno;
+				--tp->cno; /* No worry for out of bounds. */
 				++tp->owrite;
 				if (FL_ISSET(is_flags, IS_RUNNING))
 					tp->lb[tp->cno] = ' ';
-				if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
-					break;
 			}
 			if (tp->cno > max)
 				tmp = inword((UCHAR_T)tp->lb[tp->cno - 1]);
 			while (tp->cno > max) {
+				if (tmp != inword((UCHAR_T)tp->lb[tp->cno - 1])
+				    || ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
+					break;
 				--tp->cno;
 				++tp->owrite;
 				if (FL_ISSET(is_flags, IS_RUNNING))
 					tp->lb[tp->cno] = ' ';
-				if (tmp != inword((UCHAR_T)tp->lb[tp->cno - 1])
-				    || ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
-					break;
 			}
 		}