Index: lib/libc/gdtoa/Makefile.inc =================================================================== --- lib/libc/gdtoa/Makefile.inc +++ lib/libc/gdtoa/Makefile.inc @@ -18,4 +18,10 @@ gdtoa_${src}: ${SRCTOP}/contrib/gdtoa/${src} .NOMETA ln -sf ${.ALLSRC} ${.TARGET} CFLAGS.gdtoa_${src}+=-fno-strict-aliasing +.if ${COMPILER_TYPE} == "clang" && ${COMPILER_VERSION} >= 100000 +# Avoid various floating-point optimizations that clang performs. +CFLAGS.gdtoa_${src}+= -ffp-exception-behavior=maytrap +CFLAGS.gdtoa_${src}+= -ffp-model=strict +.endif + .endfor Index: lib/libc/gdtoa/_ldtoa.c =================================================================== --- lib/libc/gdtoa/_ldtoa.c +++ lib/libc/gdtoa/_ldtoa.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -38,6 +39,8 @@ #include "fpmath.h" #include "gdtoaimp.h" +/* #pragma STDC FENV_ACCESS ON */ + /* * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), * except that the floating point argument is passed by reference. @@ -65,6 +68,7 @@ union IEEEl2bits u; uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; void *vbits = bits; + int was_inexact = fetestexcept(FE_INEXACT); u.e = *ld; @@ -106,5 +110,12 @@ ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); if (*decpt == -32768) *decpt = INT_MAX; + /* + * Mask the inexact flag that can be set by gdtoa due to (k = (int)ds;) + * to prevent printf() from changing the floating point exception flags. + */ + if (!was_inexact) { + feclearexcept(FE_INEXACT); + } return ret; } Index: lib/libc/stdio/gdtoa_wrapper.h =================================================================== --- /dev/null +++ lib/libc/stdio/gdtoa_wrapper.h @@ -0,0 +1,54 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2021 Alex Richardson + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * This work was supported by Innovate UK project 105694, "Digital Security by + * Design (DSbD) Technology Platform Prototype". + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include + +/* + * Mask the inexact flag that can be set by dtoa due to (k = (int)ds;) to + * prevent printf() from changing the floating point exception flags. + */ +extern char *__dtoa(double, int, int, int *, int *, char **); +#define dtoa(...) \ + ({ \ + /* TODO: _Pragma("STDC FENV_ACCESS ON"); */ \ + int was_inexact = fetestexcept(FE_INEXACT); \ + char *result = __dtoa(__VA_ARGS__); \ + if (!was_inexact) { \ + feclearexcept(FE_INEXACT); \ + } \ + result; \ + }) +#define freedtoa __freedtoa +extern void __freedtoa(char *s); Index: lib/libc/stdio/printfcommon.h =================================================================== --- lib/libc/stdio/printfcommon.h +++ lib/libc/stdio/printfcommon.h @@ -46,14 +46,10 @@ #ifndef NO_FLOATING_POINT - -#define dtoa __dtoa -#define freedtoa __freedtoa - #include #include #include "floatio.h" -#include "gdtoa.h" +#include "gdtoa_wrapper.h" #define DEFPREC 6 Index: lib/libc/stdio/xprintf_float.c =================================================================== --- lib/libc/stdio/xprintf_float.c +++ lib/libc/stdio/xprintf_float.c @@ -41,13 +41,9 @@ #include #include #include - -#define dtoa __dtoa -#define freedtoa __freedtoa - #include #include -#include "gdtoa.h" +#include "gdtoa_wrapper.h" #include "floatio.h" #include "printf.h" #include