protect against long double type mismatches (mainly powerpc for now)
authorRich Felker <dalias@aerifal.cx>
Fri, 2 Aug 2013 23:34:22 +0000 (19:34 -0400)
committerRich Felker <dalias@aerifal.cx>
Fri, 2 Aug 2013 23:34:22 +0000 (19:34 -0400)
check in configure to be polite (failing early if we're going to fail)
and in vfprintf.c since that is the point at which a mismatching type
would be extremely dangerous.

configure
src/stdio/vfprintf.c

index 1d73472..48465f7 100755 (executable)
--- a/configure
+++ b/configure
@@ -393,6 +393,27 @@ test "$ARCH" = "microblaze" && trycppif __MICROBLAZEEL__ "$t" \
 test "$SUBARCH" \
 && printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH"
 
+#
+# Some archs (powerpc) have different possible long double formats
+# that the compiler can be configured for. The logic for whether this
+# is supported is in bits/float.h; in general, it is not. We need to
+# check for mismatches here or code in printf, strotd, and scanf will
+# be dangerously incorrect because it depends on (1) the macros being
+# correct, and (2) IEEE semantics.
+#
+printf "checking whether compiler's long double definition matches float.h... "
+echo '#include <float.h>' > "$tmpc"
+echo '#if LDBL_MANT_DIG == 53' >> "$tmpc"
+echo 'typedef char ldcheck[9-(int)sizeof(long double)];' >> "$tmpc"
+echo '#endif' >> "$tmpc"
+if $CC $CFLAGS_C99FSE -I./arch/$ARCH -I./include $CPPFLAGS $CFLAGS \
+  -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
+printf "yes\n"
+else
+printf "no\n"
+fail "$0: error: unsupported long double type"
+fi
+
 printf "creating config.mak... "
 
 exec 3>&1 1>config.mak
index 1e7e6a4..a2b287b 100644 (file)
@@ -198,6 +198,13 @@ static char *fmt_u(uintmax_t x, char *s)
        return s;
 }
 
+/* Do not override this check. The floating point printing code below
+ * depends on the float.h constants being right. If they are wrong, it
+ * may overflow the stack. */
+#if LDBL_MANT_DIG == 53
+typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
+#endif
+
 static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
 {
        uint32_t big[(LDBL_MAX_EXP+LDBL_MANT_DIG)/9+1];