NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: lib/57250: dtoa mishandles infinite doubles on 32bit big endian machines



...and after Christos massaged the code to do more code sharing
(and delete some now-un-needed code), and fixing the
non-WIDE_DOUBLE build issues, this is the resulting diff.

- Havard

------------------------------

Index: include/extern.h
===================================================================
RCS file: /cvsroot/src/lib/libc/include/extern.h,v
retrieving revision 1.26
diff -u -p -r1.26 extern.h
--- include/extern.h	15 May 2020 14:37:21 -0000	1.26
+++ include/extern.h	4 Apr 2023 18:44:22 -0000
@@ -49,11 +49,17 @@ struct sigaction;
 int __sigaction_sigtramp(int, const struct sigaction *,
     struct sigaction *, const void *, int);
 
+/* is "long double" and "double" different? */
+#if (__LDBL_MANT_DIG__ != __DBL_MANT_DIG__) || \
+    (__LDBL_MAX_EXP__ != __DBL_MAX_EXP__)
+#define WIDE_DOUBLE
+#endif
+
 #ifdef WIDE_DOUBLE
-char *__hdtoa(double, const char *, int, int *, int *, char **);
 char *__hldtoa(long double, const char *, int, int *, int *,  char **);
 char *__ldtoa(long double *, int, int, int *, int *, char **);
 #endif
+char *__hdtoa(double, const char *, int, int *, int *, char **);
 
 #ifndef __LIBC12_SOURCE__
 struct syslog_data;
Index: stdio/Makefile.inc
===================================================================
RCS file: /cvsroot/src/lib/libc/stdio/Makefile.inc,v
retrieving revision 1.47
diff -u -p -r1.47 Makefile.inc
--- stdio/Makefile.inc	29 Dec 2015 17:55:23 -0000	1.47
+++ stdio/Makefile.inc	4 Apr 2023 18:44:22 -0000
@@ -4,8 +4,6 @@
 # stdio sources
 .PATH: ${.CURDIR}/stdio
 
-CPPFLAGS+=-DWIDE_DOUBLE
-
 SRCS+=	clrerr.c dprintf.c fclose.c fdopen.c feof.c ferror.c \
 	fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetstr.c fgetwc.c \
 	fgetwln.c fgetws.c fileno.c findfp.c flags.c flockfile.c fopen.c \
Index: stdio/vfwprintf.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdio/vfwprintf.c,v
retrieving revision 1.39
diff -u -p -r1.39 vfwprintf.c
--- stdio/vfwprintf.c	19 Apr 2022 20:32:16 -0000	1.39
+++ stdio/vfwprintf.c	4 Apr 2023 18:44:22 -0000
@@ -581,9 +581,6 @@ WDECL(vf,printf_l)(FILE * __restrict fp,
 #define	DEFPREC		6
 
 static int exponent(CHAR_T *, int, int);
-#ifndef WIDE_DOUBLE
-static char *cvt(double, int, int, char *, int *, int, int *);
-#endif
 
 #endif /* !NO_FLOATING_POINT */
 
@@ -650,16 +647,15 @@ WDECL(__vf,printf_unlocked_l)(FILE *fp, 
 	 */
 	char *decimal_point;	/* locale specific decimal point */
 #ifdef WIDE_DOUBLE
-	int signflag;		/* true if float is negative */
 	union {			/* floating point arguments %[aAeEfFgG] */
 		double dbl;
 		long double ldbl;
 	} fparg;
-	char *dtoaend;		/* pointer to end of converted digits */
 #else
 	double _double;		/* double precision arguments %[eEfgG] */
-	char softsign;		/* temporary negative sign for floats */
 #endif
+	int signflag;		/* true if float is negative */
+	char *dtoaend;		/* pointer to end of converted digits */
 	char *dtoaresult;	/* buffer allocated by dtoa */
 	int expt;		/* integer value of exponent */
 	char expchar;		/* exponent character: [eEpP\0] */
@@ -1058,7 +1054,6 @@ reswitch:	switch (ch) {
 			base = 10;
 			goto number;
 #ifndef NO_FLOATING_POINT
-#ifdef WIDE_DOUBLE
 		case 'a':
 		case 'A':
 			if (ch == 'a') {
@@ -1072,6 +1067,7 @@ reswitch:	switch (ch) {
 			}
 			if (prec >= 0)
 				prec++;
+#ifdef WIDE_DOUBLE
 			if (flags & LONGDBL) {
 				fparg.ldbl = GETARG(long double);
 				dtoaresult =
@@ -1083,6 +1079,12 @@ reswitch:	switch (ch) {
 				    __hdtoa(fparg.dbl, xdigs, prec,
 				        &expt, &signflag, &dtoaend);
 			}
+#else
+			_double = GETARG(double);
+			dtoaresult =
+			  __hdtoa(_double, xdigs, prec,
+				  &expt, &signflag, &dtoaend);
+#endif /* WIDE_DOUBLE */
 			if (dtoaresult == NULL)
 				goto oomem;
 			
@@ -1127,6 +1129,7 @@ reswitch:	switch (ch) {
 fp_begin:
 			if (prec < 0)
 				prec = DEFPREC;
+#ifdef WIDE_DOUBLE
 			if (flags & LONGDBL) {
 				fparg.ldbl = GETARG(long double);
 				dtoaresult =
@@ -1140,6 +1143,14 @@ fp_begin:
 				if (expt == 9999)
 					expt = INT_MAX;
 			}
+#else
+			_double = GETARG(double);
+				dtoaresult =
+				    __dtoa(_double, expchar ? 2 : 3, prec,
+				    &expt, &signflag, &dtoaend);
+				if (expt == 9999)
+					expt = INT_MAX;
+#endif /* WIDE_DOUBLE */
 			if (dtoaresult == NULL)
 				goto oomem;
 			_DIAGASSERT(__type_fit(int, dtoaend - dtoaresult));
@@ -1170,67 +1181,8 @@ fp_common:
 				flags &= ~ZEROPAD;
 				break;
 			}
-#else
-		case 'e':
-		case 'E':
-		case 'f':
-		case 'F':
-		case 'g':
-		case 'G':
-			if (prec == -1) {
-				prec = DEFPREC;
-			} else if ((ch == 'g' || ch == 'G') && prec == 0) {
-				prec = 1;
-			}
-
-			if (flags & LONGDBL) {
-				_double = (double) GETARG(long double);
-			} else {
-				_double = GETARG(double);
-			}
-
-			/* do this before tricky precision changes */
-			if (isinf(_double)) {
-				if (_double < 0)
-					sign = '-';
-				if (ch == 'E' || ch == 'F' || ch == 'G')
-					result = STRCONST("INF");
-				else
-					result = STRCONST("inf");
-				size = 3;
-				flags &= ~ZEROPAD;
-				break;
-			}
-			if (isnan(_double)) {
-				if (ch == 'E' || ch == 'F' || ch == 'G')
-					result = STRCONST("NAN");
-				else
-					result = STRCONST("nan");
-				size = 3;
-				flags &= ~ZEROPAD;
-				break;
-			}
 
 			flags |= FPT;
-			dtoaresult = cvt(_double, prec, flags, &softsign,
-			    &expt, ch, &ndig);
-			if (dtoaresult == NULL)
-				goto oomem;
-			if (convbuf != NULL)
-				free(convbuf);
-#ifndef NARROW
-			result = convbuf = __mbsconv(dtoaresult, -1, loc);
-#else
-			/*XXX inefficient*/
-			result = convbuf = strdup(dtoaresult);
-#endif
-			if (result == NULL)
-				goto oomem;
-			__freedtoa(dtoaresult);
-			if (softsign)
-				sign = '-';
-#endif
-			flags |= FPT;
 			if (ch == 'g' || ch == 'G') {
 				if (expt > -4 && expt <= prec) {
 					/* Make %[gG] smell like %[fF] */
@@ -2001,57 +1953,7 @@ __grow_type_table (size_t nextarg, enum 
 	return 0;
 }
 
-
 #ifndef NO_FLOATING_POINT
-#ifndef WIDE_DOUBLE
-static char *
-cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch,
-    int *length)
-{
-	int mode, dsgn;
-	char *digits, *bp, *rve;
-
-	_DIAGASSERT(decpt != NULL);
-	_DIAGASSERT(length != NULL);
-	_DIAGASSERT(sign != NULL);
-
-	if (ch == 'f') {
-		mode = 3;		/* ndigits after the decimal point */
-	} else {
-		/* To obtain ndigits after the decimal point for the 'e' 
-		 * and 'E' formats, round to ndigits + 1 significant 
-		 * figures.
-		 */
-		if (ch == 'e' || ch == 'E') {
-			ndigits++;
-		}
-		mode = 2;		/* ndigits significant digits */
-	}
-
-	digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
-	if (digits == NULL)
-		return NULL;
-	if (dsgn) {
-		value = -value;
-		*sign = '-';
-	} else
-		*sign = '\000';
-	if ((ch != 'g' && ch != 'G') || flags & ALT) {	/* Print trailing zeros */
-		bp = digits + ndigits;
-		if (ch == 'f') {
-			if (*digits == '0' && value)
-				*decpt = -ndigits + 1;
-			bp += *decpt;
-		}
-		if (value == 0)	/* kludge for __dtoa irregularity */
-			rve = bp;
-		while (rve < bp)
-			*rve++ = '0';
-	}
-	*length = rve - digits;
-	return digits;
-}
-#endif
 
 static int
 exponent(CHAR_T *p0, int expo, int fmtch)


Home | Main Index | Thread Index | Old Index