bin/77031: [patch] comm(1) unable to handle lines greater than LINE_MAX (2048)

Mario Hoerich lists at MHoerich.de
Fri Feb 4 21:05:17 PST 2005


# Fergus Cameron:

[ My patch ]
> personally i think you should post it 'as is' even if you
> don't think it's worth putting extra effort into.  the neater
> reference is good to have in the PR.

(See below)

[ Loop termination ]
> 
> that is the only case it terminates at.  i think my comments
> must be ill concieved because the comment directly above
> states
> 
> 	"... stop at EOF (nb: will break from loop at end of line)"

Ooops. It wasn't your comments at fault here, it was a rather
bad case of problem between keyboard and chair. Should have
read the code in a quieter moment. My apologies for that.

Anyway, I managed to dig up both coffee and time and changed my
code to get rid of at least some malloc()ing. Don't see an easy
way to merge with your patchset though.

Regards,
Mario


Index: comm.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/comm/comm.c,v
retrieving revision 1.21
diff -u -r1.21 comm.c
--- comm.c	2 Jul 2004 22:48:29 -0000	1.21
+++ comm.c	5 Feb 2005 04:45:31 -0000
@@ -59,14 +59,19 @@
 #include <wchar.h>
 #include <wctype.h>
 
-#define	MAXLINELEN	(LINE_MAX + 1)
+struct wcstr {
+	wchar_t		*data;
+	size_t		 len;
+};
+typedef struct wcstr  wcstr_t;
 
 const wchar_t *tabs[] = { L"", L"\t", L"\t\t" };
 
 FILE   *file(const char *);
-void	show(FILE *, const char *, const wchar_t *, wchar_t *);
+void	show(FILE *, const char *, const wchar_t *, wcstr_t *);
 int     wcsicoll(const wchar_t *, const wchar_t *);
-static void	usage(void);
+wchar_t *fgetwlna(FILE *, wcstr_t *);
+static void usage(void);
 
 int
 main(int argc, char *argv[])
@@ -75,8 +80,8 @@
 	int ch, flag1, flag2, flag3, iflag;
 	FILE *fp1, *fp2;
 	const wchar_t *col1, *col2, *col3;
-	wchar_t line1[MAXLINELEN], line2[MAXLINELEN];
 	const wchar_t **p;
+	wcstr_t line1, line2;
 
 	flag1 = flag2 = flag3 = 1;
 	iflag = 0;
@@ -119,16 +124,18 @@
 		col2 = *p++;
 	if (flag3)
 		col3 = *p;
-
+	
+	memset(&line1, 0, sizeof(wcstr_t));
+	memset(&line2, 0, sizeof(wcstr_t));
 	for (read1 = read2 = 1;;) {
 		/* read next line, check for EOF */
 		if (read1) {
-			file1done = !fgetws(line1, MAXLINELEN, fp1);
+			file1done = !fgetwlna(fp1, &line1);
 			if (file1done && ferror(fp1))
 				err(1, "%s", argv[0]);
 		}
 		if (read2) {
-			file2done = !fgetws(line2, MAXLINELEN, fp2);
+			file2done = !fgetwlna(fp2, &line2);
 			if (file2done && ferror(fp2))
 				err(1, "%s", argv[1]);
 		}
@@ -136,25 +143,25 @@
 		/* if one file done, display the rest of the other file */
 		if (file1done) {
 			if (!file2done && col2)
-				show(fp2, argv[1], col2, line2);
+				show(fp2, argv[1], col2, &line2);
 			break;
 		}
 		if (file2done) {
 			if (!file1done && col1)
-				show(fp1, argv[0], col1, line1);
+				show(fp1, argv[0], col1, &line1);
 			break;
 		}
 
 		/* lines are the same */
 		if(iflag)
-			comp = wcsicoll(line1, line2);
+			comp = wcsicoll(line1.data, line2.data);
 		else
-			comp = wcscoll(line1, line2);
+			comp = wcscoll(line1.data, line2.data);
 
 		if (!comp) {
 			read1 = read2 = 1;
 			if (col3)
-				(void)printf("%ls%ls", col3, line1);
+				(void)printf("%ls%ls", col3, line1.data);
 			continue;
 		}
 
@@ -163,24 +170,25 @@
 			read1 = 1;
 			read2 = 0;
 			if (col1)
-				(void)printf("%ls%ls", col1, line1);
+				(void)printf("%ls%ls", col1, line1.data);
 		} else {
 			read1 = 0;
 			read2 = 1;
 			if (col2)
-				(void)printf("%ls%ls", col2, line2);
+				(void)printf("%ls%ls", col2, line2.data);
 		}
 	}
+	free(line1.data);
+	free(line2.data);
 	exit(0);
 }
 
 void
-show(FILE *fp, const char *fn, const wchar_t *offset, wchar_t *buf)
+show(FILE *fp, const char *fn, const wchar_t *offset, wcstr_t *buf)
 {
-
 	do {
-		(void)printf("%ls%ls", offset, buf);
-	} while (fgetws(buf, MAXLINELEN, fp));
+		(void)printf("%ls%ls", offset, buf->data);
+	} while (fgetwlna(fp, buf));
 	if (ferror(fp))
 		err(1, "%s", fn);
 }
@@ -208,13 +216,52 @@
 int
 wcsicoll(const wchar_t *s1, const wchar_t *s2)
 {
-	wchar_t *p, line1[MAXLINELEN], line2[MAXLINELEN];
-
+	wchar_t *p, *line1, *line2;
+	int cmp;
+	
+	if( (line1=malloc((wcslen(s1) + 1) * sizeof(wchar_t))) == NULL)
+		err(1, "%s", __func__);
+		
+	if( (line2=malloc((wcslen(s2) + 1) * sizeof(wchar_t))) == NULL)
+		err(1, "%s", __func__);
+		
 	for (p = line1; *s1; s1++)
 		*p++ = towlower(*s1);
-	*p = '\0';
+	*p = L'\0';
 	for (p = line2; *s2; s2++)
 		*p++ = towlower(*s2);
-	*p = '\0';
-	return (wcscoll(line1, line2));
+	*p = L'\0';
+
+	cmp = wcscoll(line1, line2);
+	free(line1);
+	free(line2);
+	
+	return cmp;
+}
+
+wchar_t *
+fgetwlna(FILE *fp, wcstr_t *str)
+{
+	size_t		 len;
+	wchar_t		*wtmp;
+
+	if(str == NULL)
+		errx(1, "%s: Empty string received.", __func__);
+		
+	if( (wtmp=fgetwln(fp,&len)) == NULL)
+		return NULL;
+		
+	/* Realloc if not enough space for string */
+	if(str->len < len + 1) { 
+		str->len  = (len + 1);
+		str->data = reallocf(str->data, str->len * sizeof(wchar_t));
+		if(str->data == NULL)
+			err(1, "%s", __func__);
+	}	
+	
+	/* can't use wcscpy as wtmp doesn't end with L'\0' */
+	wcsncpy(str->data, wtmp, len);
+	str->data[len] = L'\0';
+
+	return str->data;
 }

-- 



More information about the freebsd-bugs mailing list