Module Name:    src
Committed By:   abhinav
Date:           Sun Jun 12 13:29:29 UTC 2016

Modified Files:
        src/usr.bin/ul: Makefile ul.c

Log Message:
Fix a buffer overflow when reading from files containing extra long lines.
Instead of using a statically allocated buffer, manage the buffer at run-time
and reallocate as needed.

It was dumping core for following two cases:
man evrpc | ul
man xdm | ul

While there, also remove __P macro from function prototypes.

Ok from Christos.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/usr.bin/ul/Makefile
cvs rdiff -u -r1.16 -r1.17 src/usr.bin/ul/ul.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/ul/Makefile
diff -u src/usr.bin/ul/Makefile:1.6 src/usr.bin/ul/Makefile:1.7
--- src/usr.bin/ul/Makefile:1.6	Wed Feb  3 15:34:46 2010
+++ src/usr.bin/ul/Makefile	Sun Jun 12 13:29:29 2016
@@ -1,8 +1,8 @@
-#	$NetBSD: Makefile,v 1.6 2010/02/03 15:34:46 roy Exp $
+#	$NetBSD: Makefile,v 1.7 2016/06/12 13:29:29 abhinav Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/6/93
 
 PROG=	ul
 DPADD=	${LIBTERMINFO}
-LDADD=	-lterminfo
+LDADD=	-lterminfo -lutil
 
 .include <bsd.prog.mk>

Index: src/usr.bin/ul/ul.c
diff -u src/usr.bin/ul/ul.c:1.16 src/usr.bin/ul/ul.c:1.17
--- src/usr.bin/ul/ul.c:1.16	Tue Mar 20 20:34:59 2012
+++ src/usr.bin/ul/ul.c	Sun Jun 12 13:29:29 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ul.c,v 1.16 2012/03/20 20:34:59 matt Exp $	*/
+/*	$NetBSD: ul.c,v 1.17 2016/06/12 13:29:29 abhinav Exp $	*/
 
 /*
  * Copyright (c) 1980, 1993
@@ -39,14 +39,16 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 19
 #if 0
 static char sccsid[] = "@(#)ul.c	8.1 (Berkeley) 6/6/93";
 #endif
-__RCSID("$NetBSD: ul.c,v 1.16 2012/03/20 20:34:59 matt Exp $");
+__RCSID("$NetBSD: ul.c,v 1.17 2016/06/12 13:29:29 abhinav Exp $");
 #endif /* not lint */
 
+#include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <term.h>
 #include <unistd.h>
+#include <util.h>
 
 #define	IESC	'\033'
 #define	SO	'\016'
@@ -74,25 +76,25 @@ struct	CHAR	{
 	char	c_char;
 } ;
 
-struct	CHAR	obuf[MAXBUF];
-int	col, maxcol;
+size_t col, maxcol;
 int	mode;
 int	halfpos;
 int	upln;
 int	iflag;
 
-int	main __P((int, char **));
-void	filter __P((FILE *));
-void	flushln __P((void));
-void	fwd __P((void));
-void	iattr __P((void));
-void	initbuf __P((void));
-void	initcap __P((void));
-void	outc __P((int));
-int	outchar __P((int));
-void	overstrike __P((void));
-void	reverse __P((void));
-void	setulmode __P((int));
+void filter(FILE *);
+void flushln(struct CHAR *, size_t);
+void fwd(struct CHAR *, size_t);
+void iattr(struct CHAR *);
+void initbuf(struct CHAR *, size_t);
+void initcap(void);
+void outc(int);
+int outchar(int);
+void overstrike(struct CHAR *);
+void reverse(struct CHAR *, size_t);
+void setulmode(int);
+static void alloc_buf(struct CHAR **, size_t *);
+static void set_mode(void);
 
 
 #define	PRINT(s)	if (s == NULL) /* void */; else tputs(s, 1, outchar)
@@ -128,19 +130,19 @@ main(int argc, char **argv)
 	setupterm(termtype, 0, NULL);
 	if ((over_strike && enter_bold_mode == NULL) ||
 	    (transparent_underline && enter_underline_mode == NULL &&
-	     underline_char == NULL))
-	initbuf();
+		underline_char == NULL)) {
+		set_mode();
+	}
 	if (optind == argc)
 		filter(stdin);
-	else for (; optind<argc; optind++) {
-		f = fopen(argv[optind],"r");
-		if (f == NULL) {
-			perror(argv[optind]);
-			exit(1);
+	else {
+		for (; optind < argc; optind++) {
+			f = fopen(argv[optind], "r");
+			if (f == NULL)
+				err(EXIT_FAILURE, "Failed to open `%s'", argv[optind]);
+			filter(f);
+			fclose(f);
 		}
-
-		filter(f);
-		fclose(f);
 	}
 	exit(0);
 }
@@ -149,6 +151,9 @@ void
 filter(FILE *f)
 {
 	int c;
+	struct	CHAR *obuf = NULL;
+	size_t obuf_size = 0;
+	alloc_buf(&obuf, &obuf_size);
 
 	while ((c = getc(f)) != EOF) switch(c) {
 
@@ -161,6 +166,8 @@ filter(FILE *f)
 		col = (col+8) & ~07;
 		if (col > maxcol)
 			maxcol = col;
+		if (col >= obuf_size)
+			alloc_buf(&obuf, &obuf_size);
 		continue;
 
 	case '\r':
@@ -187,7 +194,7 @@ filter(FILE *f)
 				halfpos--;
 			} else {
 				halfpos = 0;
-				reverse();
+				reverse(obuf, obuf_size);
 			}
 			continue;
 
@@ -200,12 +207,12 @@ filter(FILE *f)
 				halfpos++;
 			} else {
 				halfpos = 0;
-				fwd();
+				fwd(obuf, obuf_size);
 			}
 			continue;
 
 		case FREV:
-			reverse();
+			reverse(obuf, obuf_size);
 			continue;
 
 		default:
@@ -214,7 +221,6 @@ filter(FILE *f)
 				IESC, c);
 			exit(1);
 		}
-		continue;
 
 	case '_':
 		if (obuf[col].c_char)
@@ -225,14 +231,16 @@ filter(FILE *f)
 		col++;
 		if (col > maxcol)
 			maxcol = col;
+		if (col >= obuf_size)
+			alloc_buf(&obuf, &obuf_size);
 		continue;
 
 	case '\n':
-		flushln();
+		flushln(obuf, obuf_size);
 		continue;
 
 	case '\f':
-		flushln();
+		flushln(obuf, obuf_size);
 		putchar('\f');
 		continue;
 
@@ -252,17 +260,21 @@ filter(FILE *f)
 		col++;
 		if (col > maxcol)
 			maxcol = col;
+		if (col >= obuf_size)
+			alloc_buf(&obuf, &obuf_size);
 		continue;
 	}
 	if (maxcol)
-		flushln();
+		flushln(obuf, obuf_size);
+
+	free(obuf);
 }
 
 void
-flushln(void)
+flushln(struct CHAR *obuf, size_t obuf_size)
 {
 	int lastmode;
-	int i;
+	size_t i;
 	int hadmodes = 0;
 
 	lastmode = NORMAL;
@@ -286,14 +298,14 @@ flushln(void)
 		setulmode(0);
 	}
 	if (must_overstrike && hadmodes)
-		overstrike();
+		overstrike(obuf);
 	putchar('\n');
 	if (iflag && hadmodes)
-		iattr();
+		iattr(obuf);
 	(void)fflush(stdout);
 	if (upln)
 		upln--;
-	initbuf();
+	initbuf(obuf, obuf_size);
 }
 
 /*
@@ -301,9 +313,9 @@ flushln(void)
  * We don't do anything with halfline ups and downs, or Greek.
  */
 void
-overstrike(void)
+overstrike(struct CHAR *obuf)
 {
-	int i;
+	size_t i;
 	char lbuf[256];
 	char *cp = lbuf;
 	int hadbold=0;
@@ -339,9 +351,9 @@ overstrike(void)
 }
 
 void
-iattr(void)
+iattr(struct CHAR *obuf)
 {
-	int i;
+	size_t i;
 	char lbuf[256];
 	char *cp = lbuf;
 
@@ -363,32 +375,38 @@ iattr(void)
 }
 
 void
-initbuf(void)
+initbuf(struct CHAR *obuf, size_t obuf_size)
 {
 
-	memset((char *)obuf, 0, sizeof (obuf));	/* depends on NORMAL == 0 */
+	memset(obuf, 0, obuf_size * sizeof(*obuf));	/* depends on NORMAL == 0 */
 	col = 0;
 	maxcol = 0;
+	set_mode();
+}
+
+static void
+set_mode(void)
+{
 	mode &= ALTSET;
 }
 
 void
-fwd(void)
+fwd(struct CHAR *obuf, size_t obuf_size)
 {
 	int oldcol, oldmax;
 
 	oldcol = col;
 	oldmax = maxcol;
-	flushln();
+	flushln(obuf, obuf_size);
 	col = oldcol;
 	maxcol = oldmax;
 }
 
 void
-reverse(void)
+reverse(struct CHAR *obuf, size_t obuf_size)
 {
 	upln++;
-	fwd();
+	fwd(obuf, obuf_size);
 	PRINT(cursor_up);
 	PRINT(cursor_up);
 	upln++;
@@ -484,3 +502,16 @@ setulmode(int newmode)
 	}
 	curmode = newmode;
 }
+
+/*
+ * Reallocates the buffer pointed to by *buf and sets
+ * the newly allocated set of bytes to 0.
+ */
+void
+alloc_buf(struct CHAR **buf, size_t *size)
+{
+        size_t osize = *size;
+        *size += MAXBUF;
+        ereallocarr(buf, *size, sizeof(**buf));
+        memset(*buf + osize, 0, (*size - osize) * sizeof(**buf));
+}

Reply via email to