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 unified 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,32 +1,32 @@ @@ -1,32 +1,32 @@
1/* $NetBSD: v_txt.c,v 1.6 2018/08/07 08:05:47 rin Exp $ */ 1/* $NetBSD: v_txt.c,v 1.7 2020/07/07 10:58:43 rin Exp $ */
2/*- 2/*-
3 * Copyright (c) 1993, 1994 3 * Copyright (c) 1993, 1994
4 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved. 6 * Keith Bostic. All rights reserved.
7 * 7 *
8 * See the LICENSE file for redistribution information. 8 * See the LICENSE file for redistribution information.
9 */ 9 */
10 10
11#include "config.h" 11#include "config.h"
12 12
13#include <sys/cdefs.h> 13#include <sys/cdefs.h>
14#if 0 14#if 0
15#ifndef lint 15#ifndef lint
16static 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 "; 16static 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 ";
17#endif /* not lint */ 17#endif /* not lint */
18#else 18#else
19__RCSID("$NetBSD: v_txt.c,v 1.6 2018/08/07 08:05:47 rin Exp $"); 19__RCSID("$NetBSD: v_txt.c,v 1.7 2020/07/07 10:58:43 rin Exp $");
20#endif 20#endif
21 21
22#include <sys/types.h> 22#include <sys/types.h>
23#include <sys/queue.h> 23#include <sys/queue.h>
24#include <sys/stat.h> 24#include <sys/stat.h>
25#include <sys/time.h> 25#include <sys/time.h>
26 26
27#include <bitstring.h> 27#include <bitstring.h>
28#include <ctype.h> 28#include <ctype.h>
29#include <errno.h> 29#include <errno.h>
30#include <limits.h> 30#include <limits.h>
31#include <stdio.h> 31#include <stdio.h>
32#include <stdlib.h> 32#include <stdlib.h>
@@ -1108,52 +1108,50 @@ leftmargin: tp->lb[tp->cno - 1] = ' '; @@ -1108,52 +1108,50 @@ leftmargin: tp->lb[tp->cno - 1] = ' ';
1108 * <blank>'s. The difference is that the type of the first 1108 * <blank>'s. The difference is that the type of the first
1109 * erased character erased is ignored, which is exactly right 1109 * erased character erased is ignored, which is exactly right
1110 * when erasing pathname components. The edit options 1110 * when erasing pathname components. The edit options
1111 * TXT_ALTWERASE and TXT_TTYWERASE specify the 4.4BSD tty 1111 * TXT_ALTWERASE and TXT_TTYWERASE specify the 4.4BSD tty
1112 * interface and the historic tty driver behavior, 1112 * interface and the historic tty driver behavior,
1113 * respectively, and the default is the same as the historic 1113 * respectively, and the default is the same as the historic
1114 * vi behavior. 1114 * vi behavior.
1115 * 1115 *
1116 * Overwrite erased characters if doing incremental search; 1116 * Overwrite erased characters if doing incremental search;
1117 * see comment above. 1117 * see comment above.
1118 */ 1118 */
1119 if (LF_ISSET(TXT_TTYWERASE)) 1119 if (LF_ISSET(TXT_TTYWERASE))
1120 while (tp->cno > max) { 1120 while (tp->cno > max) {
 1121 if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
 1122 break;
1121 --tp->cno; 1123 --tp->cno;
1122 ++tp->owrite; 1124 ++tp->owrite;
1123 if (FL_ISSET(is_flags, IS_RUNNING)) 1125 if (FL_ISSET(is_flags, IS_RUNNING))
1124 tp->lb[tp->cno] = ' '; 1126 tp->lb[tp->cno] = ' ';
1125 if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1])) 
1126 break; 
1127 } 1127 }
1128 else { 1128 else {
1129 if (LF_ISSET(TXT_ALTWERASE)) { 1129 if (LF_ISSET(TXT_ALTWERASE)) {
1130 --tp->cno; 1130 --tp->cno; /* No worry for out of bounds. */
1131 ++tp->owrite; 1131 ++tp->owrite;
1132 if (FL_ISSET(is_flags, IS_RUNNING)) 1132 if (FL_ISSET(is_flags, IS_RUNNING))
1133 tp->lb[tp->cno] = ' '; 1133 tp->lb[tp->cno] = ' ';
1134 if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1])) 
1135 break; 
1136 } 1134 }
1137 if (tp->cno > max) 1135 if (tp->cno > max)
1138 tmp = inword((UCHAR_T)tp->lb[tp->cno - 1]); 1136 tmp = inword((UCHAR_T)tp->lb[tp->cno - 1]);
1139 while (tp->cno > max) { 1137 while (tp->cno > max) {
 1138 if (tmp != inword((UCHAR_T)tp->lb[tp->cno - 1])
 1139 || ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
 1140 break;
1140 --tp->cno; 1141 --tp->cno;
1141 ++tp->owrite; 1142 ++tp->owrite;
1142 if (FL_ISSET(is_flags, IS_RUNNING)) 1143 if (FL_ISSET(is_flags, IS_RUNNING))
1143 tp->lb[tp->cno] = ' '; 1144 tp->lb[tp->cno] = ' ';
1144 if (tmp != inword((UCHAR_T)tp->lb[tp->cno - 1]) 
1145 || ISBLANK((UCHAR_T)tp->lb[tp->cno - 1])) 
1146 break; 
1147 } 1145 }
1148 } 1146 }
1149 1147
1150 /* Reset if we deleted an incremental search character. */ 1148 /* Reset if we deleted an incremental search character. */
1151 if (FL_ISSET(is_flags, IS_RUNNING)) 1149 if (FL_ISSET(is_flags, IS_RUNNING))
1152 FL_SET(is_flags, IS_RESTART); 1150 FL_SET(is_flags, IS_RESTART);
1153 break; 1151 break;
1154 case K_VKILL: /* Restart this line. */ 1152 case K_VKILL: /* Restart this line. */
1155 /* 1153 /*
1156 * !!! 1154 * !!!
1157 * If at the beginning of the line, try and drop back to a 1155 * If at the beginning of the line, try and drop back to a
1158 * previously inserted line. Historic vi did not permit 1156 * previously inserted line. Historic vi did not permit
1159 * users to go back to previous lines. 1157 * users to go back to previous lines.