From f634655e6453e7d7ec453faa16cf4c97e4a5c630 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Fri, 2 Dec 2016 12:02:03 -0800 Subject: [PATCH] Fix wcsto* where strings begin with whitespace. The libc++ tests caught this. Test: adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests Bug: None Change-Id: I14864e006f6cf9de3f96acac6aa3eb235894f2b1 --- libc/bionic/wcstod.cpp | 20 +++++++++++++++++--- tests/stdlib_test.cpp | 6 +++++- tests/wchar_test.cpp | 6 +++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/libc/bionic/wcstod.cpp b/libc/bionic/wcstod.cpp index eb66ba030..f7bd4337f 100644 --- a/libc/bionic/wcstod.cpp +++ b/libc/bionic/wcstod.cpp @@ -32,8 +32,14 @@ #include "local.h" -template float_type wcstod(const wchar_t* str, wchar_t** end, - float_type strtod_fn(const char*, char**)) { +/// Performs wide-character string to floating point conversion. +template +float_type wcstod(const wchar_t* str, wchar_t** end, float_type strtod_fn(const char*, char**)) { + const wchar_t* original_str = str; + while (iswspace(*str)) { + str++; + } + // What's the longest span of the input that might be part of the float? size_t max_len = wcsspn(str, L"-+0123456789.xXeEpP()nNaAiIfFtTyY"); @@ -70,7 +76,15 @@ template float_type wcstod(const wchar_t* str, wchar_t** e float_type result = strtod_fn(ascii_str, &ascii_end); if (ascii_end != ascii_str + actual_len) abort(); - if (end) *end = const_cast(str) + actual_len; + if (end) { + if (actual_len == 0) { + // There was an error. We need to set the end pointer back to the original string, not the + // one we advanced past the leading whitespace. + *end = const_cast(original_str); + } else { + *end = const_cast(str) + actual_len; + } + } delete[] ascii_str; return result; diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp index 5b9442fcf..fc17cde0a 100644 --- a/tests/stdlib_test.cpp +++ b/tests/stdlib_test.cpp @@ -298,6 +298,11 @@ static void CheckStrToFloat(T fn(const char* s, char** end)) { EXPECT_PRED_FORMAT2(pred, 9.0, fn("0.9e1", nullptr)); EXPECT_PRED_FORMAT2(pred, 9.0, fn("0x1.2p3", nullptr)); + const char* s = " \t\v\f\r\n9.0"; + char* p; + EXPECT_PRED_FORMAT2(pred, 9.0, fn(s, &p)); + EXPECT_EQ(s + strlen(s), p); + EXPECT_TRUE(isnan(fn("+nan", nullptr))); EXPECT_TRUE(isnan(fn("nan", nullptr))); EXPECT_TRUE(isnan(fn("-nan", nullptr))); @@ -306,7 +311,6 @@ static void CheckStrToFloat(T fn(const char* s, char** end)) { EXPECT_TRUE(isnan(fn("nan(0xff)", nullptr))); EXPECT_TRUE(isnan(fn("-nan(0xff)", nullptr))); - char* p; EXPECT_TRUE(isnan(fn("+nanny", &p))); EXPECT_STREQ("ny", p); EXPECT_TRUE(isnan(fn("nanny", &p))); diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp index 34ed5a7da..830eb70aa 100644 --- a/tests/wchar_test.cpp +++ b/tests/wchar_test.cpp @@ -686,6 +686,11 @@ static void CheckWcsToFloat(T fn(const wchar_t* s, wchar_t** end)) { EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0.9e1", nullptr)); EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0x1.2p3", nullptr)); + const wchar_t* s = L" \t\v\f\r\n9.0"; + wchar_t* p; + EXPECT_PRED_FORMAT2(pred, 9.0, fn(s, &p)); + EXPECT_EQ(s + wcslen(s), p); + EXPECT_TRUE(isnan(fn(L"+nan", nullptr))); EXPECT_TRUE(isnan(fn(L"nan", nullptr))); EXPECT_TRUE(isnan(fn(L"-nan", nullptr))); @@ -694,7 +699,6 @@ static void CheckWcsToFloat(T fn(const wchar_t* s, wchar_t** end)) { EXPECT_TRUE(isnan(fn(L"nan(0xff)", nullptr))); EXPECT_TRUE(isnan(fn(L"-nan(0xff)", nullptr))); - wchar_t* p; EXPECT_TRUE(isnan(fn(L"+nanny", &p))); EXPECT_STREQ(L"ny", p); EXPECT_TRUE(isnan(fn(L"nanny", &p)));