From 1b18aff9ba7c06e0e41ccafd22e1a4a585f86d78 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 16 Dec 2014 14:45:32 -0800 Subject: Fix nan output in the printf family. Bug: https://code.google.com/p/android/issues/detail?id=82452 Change-Id: I51f226c8b033de6e81baeea5e6db3de6ed196f73 --- libc/upstream-openbsd/lib/libc/stdio/vfprintf.c | 7 +-- libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c | 7 +-- tests/stdio_test.cpp | 76 +++++++++++++++++++----- 3 files changed, 66 insertions(+), 24 deletions(-) diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c index 7f8ff317..5f4fb7fa 100644 --- a/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c +++ b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfprintf.c,v 1.66 2014/05/03 12:36:45 deraadt Exp $ */ +/* $OpenBSD: vfprintf.c,v 1.67 2014/12/21 00:23:30 daniel Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -753,10 +753,9 @@ fp_common: if (signflag) sign = '-'; if (expt == INT_MAX) { /* inf or nan */ - if (*cp == 'N') { + if (*cp == 'N') cp = (ch >= 'a') ? "nan" : "NAN"; - sign = '\0'; - } else + else cp = (ch >= 'a') ? "inf" : "INF"; size = 3; flags &= ~ZEROPAD; diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c index ef0ca43b..a6f41232 100644 --- a/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c +++ b/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfwprintf.c,v 1.11 2014/06/04 07:45:25 stsp Exp $ */ +/* $OpenBSD: vfwprintf.c,v 1.12 2014/12/21 00:23:30 daniel Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -731,10 +731,9 @@ fp_common: if (signflag) sign = '-'; if (expt == INT_MAX) { /* inf or nan */ - if (*cp == 'N') { + if (*cp == 'N') cp = (ch >= 'a') ? L"nan" : L"NAN"; - sign = '\0'; - } else + else cp = (ch >= 'a') ? L"inf" : L"INF"; size = 3; flags &= ~ZEROPAD; diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index 854fc7b7..de5eea34 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -364,22 +364,52 @@ TEST(stdio, snprintf_smoke) { EXPECT_STREQ("print_me_twice print_me_twice", buf); } -TEST(stdio, snprintf_f_special) { - char buf[BUFSIZ]; - snprintf(buf, sizeof(buf), "%f", nanf("")); - EXPECT_STRCASEEQ("NaN", buf); - - snprintf(buf, sizeof(buf), "%f", HUGE_VALF); - EXPECT_STRCASEEQ("Inf", buf); -} - -TEST(stdio, snprintf_g_special) { - char buf[BUFSIZ]; - snprintf(buf, sizeof(buf), "%g", nan("")); - EXPECT_STRCASEEQ("NaN", buf); - - snprintf(buf, sizeof(buf), "%g", HUGE_VAL); - EXPECT_STRCASEEQ("Inf", buf); +template +void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...), + const T* fmt, const T* fmt_plus, + const T* minus_inf, const T* inf_, const T* plus_inf, + const T* minus_nan, const T* nan_, const T* plus_nan) { + T buf[BUFSIZ]; + + snprintf_fn(buf, sizeof(buf), fmt, nan("")); + EXPECT_STREQ(nan_, buf) << fmt; + snprintf_fn(buf, sizeof(buf), fmt, -nan("")); + EXPECT_STREQ(minus_nan, buf) << fmt; + snprintf_fn(buf, sizeof(buf), fmt_plus, nan("")); + EXPECT_STREQ(plus_nan, buf) << fmt_plus; + snprintf_fn(buf, sizeof(buf), fmt_plus, -nan("")); + EXPECT_STREQ(minus_nan, buf) << fmt_plus; + + snprintf_fn(buf, sizeof(buf), fmt, HUGE_VAL); + EXPECT_STREQ(inf_, buf) << fmt; + snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VAL); + EXPECT_STREQ(minus_inf, buf) << fmt; + snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VAL); + EXPECT_STREQ(plus_inf, buf) << fmt_plus; + snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VAL); + EXPECT_STREQ(minus_inf, buf) << fmt_plus; +} + +TEST(stdio, snprintf_inf_nan) { + CheckInfNan(snprintf, "%a", "%+a", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); + CheckInfNan(snprintf, "%A", "%+A", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); + CheckInfNan(snprintf, "%e", "%+e", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); + CheckInfNan(snprintf, "%E", "%+E", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); + CheckInfNan(snprintf, "%f", "%+f", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); + CheckInfNan(snprintf, "%F", "%+F", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); + CheckInfNan(snprintf, "%g", "%+g", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); + CheckInfNan(snprintf, "%G", "%+G", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); +} + +TEST(stdio, wsprintf_inf_nan) { + CheckInfNan(swprintf, L"%a", L"%+a", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); + CheckInfNan(swprintf, L"%A", L"%+A", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); + CheckInfNan(swprintf, L"%e", L"%+e", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); + CheckInfNan(swprintf, L"%E", L"%+E", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); + CheckInfNan(swprintf, L"%f", L"%+f", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); + CheckInfNan(swprintf, L"%F", L"%+F", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); + CheckInfNan(swprintf, L"%g", L"%+g", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); + CheckInfNan(swprintf, L"%G", L"%+G", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); } TEST(stdio, snprintf_d_INT_MAX) { @@ -439,8 +469,22 @@ TEST(stdio, snprintf_e) { TEST(stdio, snprintf_negative_zero_5084292) { char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%e", -0.0); + EXPECT_STREQ("-0.000000e+00", buf); + snprintf(buf, sizeof(buf), "%E", -0.0); + EXPECT_STREQ("-0.000000E+00", buf); snprintf(buf, sizeof(buf), "%f", -0.0); EXPECT_STREQ("-0.000000", buf); + snprintf(buf, sizeof(buf), "%F", -0.0); + EXPECT_STREQ("-0.000000", buf); + snprintf(buf, sizeof(buf), "%g", -0.0); + EXPECT_STREQ("-0", buf); + snprintf(buf, sizeof(buf), "%G", -0.0); + EXPECT_STREQ("-0", buf); + snprintf(buf, sizeof(buf), "%a", -0.0); + EXPECT_STREQ("-0x0p+0", buf); + snprintf(buf, sizeof(buf), "%A", -0.0); + EXPECT_STREQ("-0X0P+0", buf); } TEST(stdio, snprintf_utf8_15439554) { -- cgit v1.2.3-54-g00ecf