VI bug

Gary Winiger gww at beatnix.UUCP
Sat Feb 20 04:11:56 AEST 1988


In article <1027 at sauron.Columbia.NCR.COM> wescott at sauron.Columbia.NCR.COM (Mike Wescott) writes:
>In a number of places in its source, vi uses isdigit() (see ctype(3))
>to check a character (encoded in an int or short) it just received.  No
>problem, except that occasionally, like just after a SIGINT, the character
>
>There may be other isxxxx() calls that have similar problems.
>
>I don't have a fix yet.  We only discovered it while playing with a
>shared library version of ctype.  And there is little probability
>
>Did isdigit() once have range checking built in?  Or was it a version
>called _isdigit()?
>

I've had the bug fix for this since Sept, sorry I haven't posted it yet.
Here it is.  This will get me off by butt and get the rest of the bug
fixes that I've been sitting on posted.

>From gww Tue Sep  8 18:16:28 1987
To: /RCS/Bugs

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

Description:
	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.
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/,RCSt1001661	Tue Sep  8 17:32:37 1987
--- ex_vget.c	Fri May  8 17:08:01 1987
***************
*** 1,5 ****
--- 1,9 ----
  /*
   * $Log:	ex_vget.c,v $
+  * 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
  
--- 15,21 ----
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_vget.c,v 1.2 87/05/08 17:06:28 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';
  	}
--- 628,634 ----
  	cnt = 0;
  	for (;;) {
  		c = getkey();
! 		if (c == ATTN || !isdigit(c))
  			break;
  		cnt *= 10, cnt += c - '0';
  	}

Index: ucb/ex/ex_vmain.c
*** /tmp/,RCSt1001666	Tue Sep  8 17:32:57 1987
--- ex_vmain.c	Fri May  8 17:08:07 1987
***************
*** 1,5 ****
--- 1,9 ----
  /*
   * $Log:	ex_vmain.c,v $
+  * 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
  
--- 15,21 ----
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_vmain.c,v 1.2 87/05/08 17:08:01 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);
--- 116,124 ----
  			if (trace)
  				fprintf(trace, "pc=%c",peekkey());
  #endif
! 			if (peekkey() != ATTN && 
! 			    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:
--- 132,139 ----
  			 * an 'empty' named buffer spec in the routine
  			 * kshift (see ex_temp.c).
  			 */
! 			forbid (c == '0' ||
! 				c != ATTN && !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;
  			}
--- 165,171 ----
  			 * to go back to the "for" to interpret it. Likewise
  			 * for a buffer name.
  			 */
! 			if ((c != ATTN && isdigit(c) && c!='0') || c == '"') {
  				ungetkey(c);
  				goto looptop;
  			}

Index: ucb/ex/ex_voper.c
*** /tmp/,RCSt1001671	Tue Sep  8 17:34:22 1987
--- ex_voper.c	Fri May  8 17:08:15 1987
***************
*** 1,5 ****
--- 1,9 ----
  /*
   * $Log:	ex_voper.c,v $
+  * 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
  
--- 15,21 ----
   */
  
  #ifndef lint
! static char *ERcsId = "$Header: ex_voper.c,v 1.2 87/05/08 17:08:08 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);
--- 137,143 ----
  	 * Had an operator, so accept another count.
  	 * Multiply counts together.
  	 */
! 	if (peekkey() != ATTN && isdigit(peekkey()) && peekkey() != '0') {
  		cnt *= vgetcnt();
  		Xcnt = cnt;
  		forbid (cnt <= 0);



More information about the Comp.bugs.sys5 mailing list