[comp.bugs.4bsd] Vi core dumps on SIGINT input. +Fix

gww@beatnix.UUCP (Gary Winiger) (03/13/88)

Subject: Vi core dumps on SIGINT input. +Fix
Index:	ucb/ex/{ex_vget.c, ex_vmain.c, ex_voper.c} 4.3BSD +Fix

Description:
	As previously reported:
	When vi receives the a SIGINT, it can queue it as the input character
	ATTN (value -2).  This character is returned by getkey() (peekkey()).
	In some cases, vi asks if the character received is an xxx with
	``isxxx''.  The ``isxxx'' macros index the array _ctype_[] to
	determine the type of the character.  If _ctype_ begins on a page
	boundary and the previous page is not a valid page, a segment fault
	will occur.
	Thanks to Keith Bostic (bostic@ucbvax) for pointing out that my
	previous fix was narrow in scope and could better be done as follows.
Repeat-By:
	vi foo
	<user types INTERRUPT character>
	When _ctype_ begins on a page boundary and the previous page is not
	valid.
Fix:
	Guard against checking indexing _ctype_ when the character may be
	ATTN.
	The attached code solves this problem at Elxsi.

Gary..
{ucbvax!sun,lll-lcc!lll-tis,amdahl!altos86,bridge2}!elxsi!gww
--------- cut --------- snip --------- :.,$w diff -------------
Index: ucb/ex/ex_vget.c
*** /tmp/,RCSt1014232	Sat Mar 12 10:57:36 1988
--- ex_vget.c	Sat Mar 12 10:56:47 1988
***************
*** 1,5 ****
--- 1,13 ----
  /*
   * $Log:	ex_vget.c,v $
+  * Revision 1.3  88/03/12  10:55:34  gww
+  * Correct guard against non-ascii index of _ctype_[].  Thanks to 
+  * Keith Bostic (bostic@ucbvax).
+  * 
+  * Revision 1.2  87/05/08  17:06:28  gww
+  * Check for ATTN (-2) before using isxxxx macro so as not to negatively
+  * index _ctype_[] and possibly get a segment fault.
+  * 
   * Revision 1.1  86/12/23  18:16:10  gww
   * Initial revision
   * 
***************
*** 11,17 ****
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_vget.c,v 1.1 86/12/23 18:16:10 gww Exp $ ENIX BSD";
  static char *sccsid = "@(#)ex_vget.c	6.8 (Berkeley) 6/7/85";
  #endif not lint
  
--- 19,25 ----
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_vget.c,v 1.3 88/03/12 10:55:34 gww Exp $ ENIX BSD";
  static char *sccsid = "@(#)ex_vget.c	6.8 (Berkeley) 6/7/85";
  #endif not lint
  
***************
*** 624,630 ****
  	cnt = 0;
  	for (;;) {
  		c = getkey();
! 		if (!isdigit(c))
  			break;
  		cnt *= 10, cnt += c - '0';
  	}
--- 632,638 ----
  	cnt = 0;
  	for (;;) {
  		c = getkey();
! 		if (!isascii(c) || !isdigit(c))
  			break;
  		cnt *= 10, cnt += c - '0';
  	}

Index: ucb/ex/ex_vmain.c
*** /tmp/,RCSt1014237	Sat Mar 12 10:57:51 1988
--- ex_vmain.c	Sat Mar 12 10:56:54 1988
***************
*** 1,5 ****
--- 1,13 ----
  /*
   * $Log:	ex_vmain.c,v $
+  * Revision 1.3  88/03/12  10:56:48  gww
+  * Correct guard against non-ascii index of _ctype_[].  Thanks to 
+  * Keith Bostic (bostic@ucbvax).
+  * 
+  * Revision 1.2  87/05/08  17:08:01  gww
+  * Check for ATTN (-2) before using isxxxx macro so as not to negatively
+  * index _ctype_[] and possibly get a segment fault.
+  * 
   * Revision 1.1  86/12/23  18:16:13  gww
   * Initial revision
   * 
***************
*** 11,17 ****
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_vmain.c,v 1.1 86/12/23 18:16:13 gww Exp $ ENIX BSD";
  static char *sccsid = "@(#)ex_vmain.c	7.7 (Berkeley) 6/7/85";
  #endif not lint
  
--- 19,25 ----
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_vmain.c,v 1.3 88/03/12 10:56:48 gww Exp $ ENIX BSD";
  static char *sccsid = "@(#)ex_vmain.c	7.7 (Berkeley) 6/7/85";
  #endif not lint
  
***************
*** 112,118 ****
  			if (trace)
  				fprintf(trace, "pc=%c",peekkey());
  #endif
! 			if (isdigit(peekkey()) && peekkey() != '0') {
  				hadcnt = 1;
  				cnt = vgetcnt();
  				forbid (cnt <= 0);
--- 120,128 ----
  			if (trace)
  				fprintf(trace, "pc=%c",peekkey());
  #endif
! 			if (isascii(peekkey()) &&
! 			    isdigit(peekkey()) && 
! 			    peekkey() != '0') {
  				hadcnt = 1;
  				cnt = vgetcnt();
  				forbid (cnt <= 0);
***************
*** 126,132 ****
  			 * an 'empty' named buffer spec in the routine
  			 * kshift (see ex_temp.c).
  			 */
! 			forbid (c == '0' || !isalpha(c) && !isdigit(c));
  			vreg = c;
  		}
  reread:
--- 136,143 ----
  			 * an 'empty' named buffer spec in the routine
  			 * kshift (see ex_temp.c).
  			 */
! 			forbid (c == '0' ||
! 				isascii(c) && !isalpha(c) && !isdigit(c));
  			vreg = c;
  		}
  reread:
***************
*** 158,164 ****
  			 * to go back to the "for" to interpret it. Likewise
  			 * for a buffer name.
  			 */
! 			if ((isdigit(c) && c!='0') || c == '"') {
  				ungetkey(c);
  				goto looptop;
  			}
--- 169,175 ----
  			 * to go back to the "for" to interpret it. Likewise
  			 * for a buffer name.
  			 */
! 			if ((isascii(c) && isdigit(c) && c!='0') || c == '"') {
  				ungetkey(c);
  				goto looptop;
  			}

Index: ucb/ex/ex_voper.c
*** /tmp/,RCSt1014242	Sat Mar 12 10:58:08 1988
--- ex_voper.c	Sat Mar 12 10:57:00 1988
***************
*** 1,5 ****
--- 1,13 ----
  /*
   * $Log:	ex_voper.c,v $
+  * Revision 1.3  88/03/12  10:56:56  gww
+  * Correct guard against non-ascii index of _ctype_[].  Thanks to 
+  * Keith Bostic (bostic@ucbvax).
+  * 
+  * Revision 1.2  87/05/08  17:08:08  gww
+  * Check for ATTN (-2) before using isxxxx macro so as not to negatively
+  * index _ctype_[] and possibly get a segment fault.
+  * 
   * Revision 1.1  86/12/23  18:16:15  gww
   * Initial revision
   * 
***************
*** 11,17 ****
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_voper.c,v 1.1 86/12/23 18:16:15 gww Exp $ ENIX BSD";
  static char *sccsid = "@(#)ex_voper.c	7.4 (Berkeley) 6/7/85";
  #endif not lint
  
--- 19,25 ----
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_voper.c,v 1.3 88/03/12 10:56:56 gww Exp $ ENIX BSD";
  static char *sccsid = "@(#)ex_voper.c	7.4 (Berkeley) 6/7/85";
  #endif not lint
  
***************
*** 133,139 ****
  	 * Had an operator, so accept another count.
  	 * Multiply counts together.
  	 */
! 	if (isdigit(peekkey()) && peekkey() != '0') {
  		cnt *= vgetcnt();
  		Xcnt = cnt;
  		forbid (cnt <= 0);
--- 141,147 ----
  	 * Had an operator, so accept another count.
  	 * Multiply counts together.
  	 */
! 	if (isascii(peekkey()) && isdigit(peekkey()) && peekkey() != '0') {
  		cnt *= vgetcnt();
  		Xcnt = cnt;
  		forbid (cnt <= 0);