svn commit: r211428 - in stable/8: tools/regression/usr.bin tools/regression/usr.bin/comm tools/regression/usr.bin/pkill usr.bin/comm

Jaakko Heinonen jh at FreeBSD.org
Tue Aug 17 15:02:34 UTC 2010


Author: jh
Date: Tue Aug 17 15:02:33 2010
New Revision: 211428
URL: http://svn.freebsd.org/changeset/base/211428

Log:
  MFC r200442:
  
  Don't read the newline character to line buffer because lines are passed
  to wcscoll(3). Newline characters could cause incorrect results when
  comparing lines.
  
  Also, if an input line didn't contain a newline character, it was
  omitted from the output. According to my interpretation, SUSv3 requires
  that the newline is always printed.
  
  Add regression tests for the cases.
  
  PR:		bin/140976
  
  MFC r200604:
  
  - Prevent overflowing of the buffer length variable in getline() by
    limiting its maximum value.
  - Exit if reallocf(3) fails in getline(). Failure was silently
    considered as end-of-file.
  
  MFC r204896 by ache:
  
  Rewrite input processing to not exit with error on the first EILSEQ found
  in the input data but fallback to "binary comparison" instead.
  
  POSIX says: "The input files shall be text files", nothing more,
  so the text file with illegal sequence is valid input.
  BTW, GNU sort does not fails on EILSEQ too.
  
  MFC r204928 by ache:
  
  Add SIZE_MAX overflow check

Added:
  stable/8/tools/regression/usr.bin/comm/
     - copied from r200442, head/tools/regression/usr.bin/comm/
Modified:
  stable/8/tools/regression/usr.bin/Makefile
  stable/8/usr.bin/comm/comm.c
Directory Properties:
  stable/8/tools/regression/usr.bin/   (props changed)
  stable/8/tools/regression/usr.bin/pkill/pgrep-_g.t   (props changed)
  stable/8/tools/regression/usr.bin/pkill/pgrep-_s.t   (props changed)
  stable/8/tools/regression/usr.bin/pkill/pkill-_g.t   (props changed)
  stable/8/tools/regression/usr.bin/sed/   (props changed)
  stable/8/usr.bin/comm/   (props changed)

Modified: stable/8/tools/regression/usr.bin/Makefile
==============================================================================
--- stable/8/tools/regression/usr.bin/Makefile	Tue Aug 17 13:02:08 2010	(r211427)
+++ stable/8/tools/regression/usr.bin/Makefile	Tue Aug 17 15:02:33 2010	(r211428)
@@ -1,5 +1,5 @@
 # $FreeBSD$
 
-SUBDIR=	apply calendar file2c join jot m4 printf sed tr uudecode uuencode xargs lastcomm
+SUBDIR=	apply calendar comm file2c join jot m4 printf sed tr uudecode uuencode xargs lastcomm
 
 .include <bsd.subdir.mk>

Modified: stable/8/usr.bin/comm/comm.c
==============================================================================
--- stable/8/usr.bin/comm/comm.c	Tue Aug 17 13:02:08 2010	(r211427)
+++ stable/8/usr.bin/comm/comm.c	Tue Aug 17 15:02:33 2010	(r211428)
@@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$");
 #include <err.h>
 #include <limits.h>
 #include <locale.h>
+#include <stdint.h>
+#define _WITH_GETLINE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -59,39 +61,31 @@ __FBSDID("$FreeBSD$");
 #include <wchar.h>
 #include <wctype.h>
 
-#define	MAXLINELEN	(LINE_MAX + 1)
-
-const wchar_t *tabs[] = { L"", L"\t", L"\t\t" };
+int iflag;
+const char *tabs[] = { "", "\t", "\t\t" };
 
 FILE   *file(const char *);
-wchar_t	*getline(wchar_t *, size_t *, FILE *);
-void	show(FILE *, const char *, const wchar_t *, wchar_t *, size_t *);
-int     wcsicoll(const wchar_t *, const wchar_t *);
+wchar_t	*convert(const char *);
+void	show(FILE *, const char *, const char *, char **, size_t *);
 static void	usage(void);
 
 int
 main(int argc, char *argv[])
 {
 	int comp, read1, read2;
-	int ch, flag1, flag2, flag3, iflag;
+	int ch, flag1, flag2, flag3;
 	FILE *fp1, *fp2;
-	const wchar_t *col1, *col2, *col3;
+	const char *col1, *col2, *col3;
 	size_t line1len, line2len;
-	wchar_t *line1, *line2;
-	const wchar_t **p;
-
-	flag1 = flag2 = flag3 = 1;
-	iflag = 0;
-
- 	line1len = MAXLINELEN;
- 	line2len = MAXLINELEN;
- 	line1 = malloc(line1len * sizeof(*line1));
- 	line2 = malloc(line2len * sizeof(*line2));
-	if (line1 == NULL || line2 == NULL)
-		err(1, "malloc");
+	char *line1, *line2;
+	ssize_t n1, n2;
+	wchar_t *tline1, *tline2;
+	const char **p;
 
 	(void) setlocale(LC_ALL, "");
 
+	flag1 = flag2 = flag3 = 1;
+
 	while ((ch = getopt(argc, argv, "123i")) != -1)
 		switch(ch) {
 		case '1':
@@ -129,41 +123,57 @@ main(int argc, char *argv[])
 	if (flag3)
 		col3 = *p;
 
+	line1len = line2len = 0;
+	line1 = line2 = NULL;
+	n1 = n2 = -1;
+
 	for (read1 = read2 = 1;;) {
 		/* read next line, check for EOF */
 		if (read1) {
-			line1 = getline(line1, &line1len, fp1);
-			if (line1 == NULL && ferror(fp1))
+			n1 = getline(&line1, &line1len, fp1);
+			if (n1 < 0 && ferror(fp1))
 				err(1, "%s", argv[0]);
+			if (n1 > 0 && line1[n1 - 1] == '\n')
+				line1[n1 - 1] = '\0';
+
 		}
 		if (read2) {
-			line2 = getline(line2, &line2len, fp2);
-			if (line2 == NULL && ferror(fp2))
+			n2 = getline(&line2, &line2len, fp2);
+			if (n2 < 0 && ferror(fp2))
 				err(1, "%s", argv[1]);
+			if (n2 > 0 && line2[n2 - 1] == '\n')
+				line2[n2 - 1] = '\0';
 		}
 
 		/* if one file done, display the rest of the other file */
-		if (line1 == NULL) {
-			if (line2 != NULL && col2 != NULL)
-				show(fp2, argv[1], col2, line2, &line2len);
+		if (n1 < 0) {
+			if (n2 >= 0 && col2 != NULL)
+				show(fp2, argv[1], col2, &line2, &line2len);
 			break;
 		}
-		if (line2 == NULL) {
-			if (line1 != NULL && col1 != NULL)
-				show(fp1, argv[0], col1, line1, &line1len);
+		if (n2 < 0) {
+			if (n1 >= 0 && col1 != NULL)
+				show(fp1, argv[0], col1, &line1, &line1len);
 			break;
 		}
 
-		/* lines are the same */
-		if(iflag)
-			comp = wcsicoll(line1, line2);
+		tline2 = NULL;
+		if ((tline1 = convert(line1)) != NULL)
+			tline2 = convert(line2);
+		if (tline1 == NULL || tline2 == NULL)
+			comp = strcmp(line1, line2);
 		else
-			comp = wcscoll(line1, line2);
+			comp = wcscoll(tline1, tline2);
+		if (tline1 != NULL)
+			free(tline1);
+		if (tline2 != NULL)
+			free(tline2);
 
+		/* lines are the same */
 		if (!comp) {
 			read1 = read2 = 1;
 			if (col3 != NULL)
-				(void)printf("%ls%ls", col3, line1);
+				(void)printf("%s%s\n", col3, line1);
 			continue;
 		}
 
@@ -172,48 +182,52 @@ main(int argc, char *argv[])
 			read1 = 1;
 			read2 = 0;
 			if (col1 != NULL)
-				(void)printf("%ls%ls", col1, line1);
+				(void)printf("%s%s\n", col1, line1);
 		} else {
 			read1 = 0;
 			read2 = 1;
 			if (col2 != NULL)
-				(void)printf("%ls%ls", col2, line2);
+				(void)printf("%s%s\n", col2, line2);
 		}
 	}
 	exit(0);
 }
 
 wchar_t *
-getline(wchar_t *buf, size_t *buflen, FILE *fp)
+convert(const char *str)
 {
-	size_t bufpos;
-	wint_t ch;
+	size_t n;
+	wchar_t *buf, *p;
 
-	bufpos = 0;
-	do {
-		if ((ch = getwc(fp)) != WEOF) {
-			if (bufpos + 2 >= *buflen) {
-				*buflen = *buflen * 2;
-				buf = reallocf(buf, *buflen * sizeof(*buf));
-				if (buf == NULL)
-					return (NULL);
-			}
-			buf[bufpos++] = ch;
-		}
-	} while (ch != WEOF && ch != '\n');
-	if (bufpos + 1 != *buflen)
-		buf[bufpos] = '\0';
+	if ((n = mbstowcs(NULL, str, 0)) == (size_t)-1)
+		return (NULL);
+	if (SIZE_MAX / sizeof(*buf) < n + 1)
+		errx(1, "conversion buffer length overflow");
+	if ((buf = malloc((n + 1) * sizeof(*buf))) == NULL)
+		err(1, "malloc");
+	if (mbstowcs(buf, str, n + 1) != n)
+		errx(1, "internal mbstowcs() error");
+
+	if (iflag) {
+		for (p = buf; *p != L'\0'; p++)
+			*p = towlower(*p);
+	}
 
-	return (bufpos != 0 || ch == '\n' ? buf : NULL);
+	return (buf);
 }
 
 void
-show(FILE *fp, const char *fn, const wchar_t *offset, wchar_t *buf, size_t *buflen)
+show(FILE *fp, const char *fn, const char *offset, char **bufp, size_t *buflenp)
 {
+	ssize_t n;
 
 	do {
-		(void)printf("%ls%ls", offset, buf);
-	} while ((buf = getline(buf, buflen, fp)) != NULL);
+		(void)printf("%s%s\n", offset, *bufp);
+		if ((n = getline(bufp, buflenp, fp)) < 0)
+			break;
+		if (n > 0 && (*bufp)[n - 1] == '\n')
+			(*bufp)[n - 1] = '\0';
+	} while (1);
 	if (ferror(fp))
 		err(1, "%s", fn);
 }
@@ -237,52 +251,3 @@ usage(void)
 	(void)fprintf(stderr, "usage: comm [-123i] file1 file2\n");
 	exit(1);
 }
-
-static size_t wcsicoll_l1_buflen = 0, wcsicoll_l2_buflen = 0;
-static wchar_t *wcsicoll_l1_buf = NULL, *wcsicoll_l2_buf = NULL;
-
-int
-wcsicoll(const wchar_t *s1, const wchar_t *s2)
-{
-	wchar_t *p;
-	size_t l1, l2;
-	size_t new_l1_buflen, new_l2_buflen;
-
-	l1 = wcslen(s1) + 1;
-	l2 = wcslen(s2) + 1;
-	new_l1_buflen = wcsicoll_l1_buflen;
-	new_l2_buflen = wcsicoll_l2_buflen;
-	while (new_l1_buflen < l1) {
-		if (new_l1_buflen == 0)
-			new_l1_buflen = MAXLINELEN;
-		else
-			new_l1_buflen *= 2;
-	}
-	while (new_l2_buflen < l2) {
-		if (new_l2_buflen == 0)
-			new_l2_buflen = MAXLINELEN;
-		else
-			new_l2_buflen *= 2;
-	}
-	if (new_l1_buflen > wcsicoll_l1_buflen) {
-		wcsicoll_l1_buf = reallocf(wcsicoll_l1_buf, new_l1_buflen * sizeof(*wcsicoll_l1_buf));
-		if (wcsicoll_l1_buf == NULL)
-                	err(1, "reallocf");
-		wcsicoll_l1_buflen = new_l1_buflen;
-	}
-	if (new_l2_buflen > wcsicoll_l2_buflen) {
-		wcsicoll_l2_buf = reallocf(wcsicoll_l2_buf, new_l2_buflen * sizeof(*wcsicoll_l2_buf));
-		if (wcsicoll_l2_buf == NULL)
-                	err(1, "reallocf");
-		wcsicoll_l2_buflen = new_l2_buflen;
-	}
-
-	for (p = wcsicoll_l1_buf; *s1; s1++)
-		*p++ = towlower(*s1);
-	*p = '\0';
-	for (p = wcsicoll_l2_buf; *s2; s2++)
-		*p++ = towlower(*s2);
-	*p = '\0';
-
-	return (wcscoll(wcsicoll_l1_buf, wcsicoll_l2_buf));
-}


More information about the svn-src-stable mailing list