Subject: Re: buffer overflows in libsa
To: None <tech-kern@NetBSD.org>
From: Roland Illig <rillig@NetBSD.org>
List: tech-kern
Date: 08/23/2005 09:01:45
This is a multi-part message in MIME format.
--------------060800090106010201010003
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Bill Studenmund wrote:
> I wouldn't object to you coming up with a getsn() or some such that took a 
> buffer length and assumed standard in. Or getsl().

Here it is.

Roland

--------------060800090106010201010003
Content-Type: text/plain;
 name="libsa-gets.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="libsa-gets.patch"

? libsa-gets.patch
Index: Makefile
===================================================================
RCS file: /cvsroot/src/sys/lib/libsa/Makefile,v
retrieving revision 1.56
diff -u -p -r1.56 Makefile
--- Makefile	13 Jun 2005 12:11:07 -0000	1.56
+++ Makefile	23 Aug 2005 07:00:06 -0000
@@ -17,8 +17,8 @@ CPPFLAGS=	-I${SADIR} ${SACPPFLAGS} ${SAM
 .PATH.c: ${SADIR}
 
 # stand routines
-SRCS+=	alloc.c bcopy.c bzero.c errno.c exit.c exec.c files.c \
-	getfile.c gets.c globals.c memcmp.c memcpy.c memmove.c memset.c \
+SRCS+=	alloc.c bcopy.c bzero.c errno.c exit.c exec.c files.c getfile.c \
+	gets.c getsl.c globals.c memcmp.c memcpy.c memmove.c memset.c \
 	panic.c printf.c qsort.c snprintf.c sprintf.c strerror.c subr_prf.c \
 	twiddle.c vsprintf.c checkpasswd.c
 
Index: gets.c
===================================================================
RCS file: /cvsroot/src/sys/lib/libsa/gets.c,v
retrieving revision 1.8
diff -u -p -r1.8 gets.c
--- gets.c	7 Aug 2003 16:32:27 -0000	1.8
+++ getsl.c	23 Aug 2005 07:00:06 -0000
@@ -1,4 +1,5 @@
-/*	$NetBSD: gets.c,v 1.8 2003/08/07 16:32:27 agc Exp $	*/
+/*	$NetBSD$	*/
+/*	From NetBSD: gets.c,v 1.8 2003/08/07 16:32:27 agc Exp	*/
 
 /*-
  * Copyright (c) 1993
@@ -33,14 +34,21 @@
 
 #include "stand.h"
 
+#define CTRL(key)	((key) & 037)
+
+/* gets(3)-like function with bounds checking */
 void
-gets(buf)
-	char *buf;
+getsl(char *buf, size_t bufsize)
 {
 	int c;
-	char *lp;
+	char *lp, *bufend;
+
+	/* assert(bufsize != 0); */
+
+	/* leave enough room for the terminating null character */
+	bufend = buf + bufsize - 1;
 
-	for (lp = buf;;)
+	for (lp = buf;;) {
 		switch (c = getchar() & 0177) {
 		case '\n':
 		case '\r':
@@ -62,7 +70,7 @@ gets(buf)
 				--lp;
 			break;
 #endif
-		case 'r'&037: {
+		case CTRL('r'): {
 			char *p;
 
 			putchar('\n');
@@ -73,14 +81,18 @@ gets(buf)
 #if AT_ERASE
 		case '@':
 #endif
-		case 'u'&037:
-		case 'w'&037:
+		case CTRL('u'):
+		case CTRL('w'):
 			lp = buf;
 			putchar('\n');
 			break;
 		default:
-			*lp++ = c;
-			putchar(c);
+			if (lp < bufend) {
+				*lp++ = c;
+				putchar(c);
+			} else
+				putchar('\a');
 		}
+	}
 	/*NOTREACHED*/
 }

--------------060800090106010201010003--