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
Hi,
based on hints from Martin, and a suggestion that the non-
WIDE_DOUBLE code misses handling for %a and %A, I came up with
this diff which at least produces one correct result for %a on
NetBSD/macppc :)
"More testing required".
Regards,
- 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 3 Apr 2023 12:33:57 -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 3 Apr 2023 12:33:57 -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 3 Apr 2023 12:33:57 -0000
@@ -650,16 +650,16 @@ 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] */
@@ -1170,7 +1170,64 @@ fp_common:
flags &= ~ZEROPAD;
break;
}
+#else /* ! WIDE_DOUBLE */
+ case 'a':
+ case 'A':
+ if (ch == 'a') {
+ ox[1] = 'x';
+ xdigs = xdigs_lower;
+ expchar = 'p';
+ } else {
+ ox[1] = 'X';
+ xdigs = xdigs_upper;
+ expchar = 'P';
+ }
+ if (prec >= 0)
+ prec++;
+
+ _double = GETARG(double);
+ dtoaresult =
+ __hdtoa(_double, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL)
+ goto oomem;
+
+ if (prec < 0) {
+ _DIAGASSERT(__type_fit(int,
+ dtoaend - dtoaresult));
+ prec = (int)(dtoaend - dtoaresult);
+ }
+ if (expt == INT_MAX)
+ ox[1] = '\0';
+ _DIAGASSERT(__type_fit(int, dtoaend - dtoaresult));
+ ndig = (int)(dtoaend - dtoaresult);
+ 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 (signflag)
+ sign = '-';
+ if (expt == INT_MAX) { /* inf or nan */
+ if (*result == 'N') {
+ result = (ch >= 'a') ? STRCONST("nan") :
+ STRCONST("NAN");
+ sign = '\0';
+ } else
+ result = (ch >= 'a') ? STRCONST("inf") :
+ STRCONST("INF");
+ size = 3;
+ flags &= ~ZEROPAD;
+ break;
+ }
+ goto fp_common_wrapup;
case 'e':
case 'E':
case 'f':
@@ -1229,7 +1286,8 @@ fp_common:
__freedtoa(dtoaresult);
if (softsign)
sign = '-';
-#endif
+#endif /* WIDE_DOUBLE */
+ fp_common_wrapup:
flags |= FPT;
if (ch == 'g' || ch == 'G') {
if (expt > -4 && expt <= prec) {
Home |
Main Index |
Thread Index |
Old Index