From bfd50863b816e829c15895df5c46f37e2927ce6a Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 6 Nov 2018 22:59:11 -0800 Subject: [PATCH] Correct fish_wcstod and fix Linux build failure Limit the fish_wcstod fast path to ASCII digits only, to fix the problem observed in the discussion for a700acadfa146a3937afd6e4e8ce861e2cc6d1f5 where LANG=de_DE.UTF-8 would cause `test` to interpret commas instead of periods inside floating point values. --- src/fish_tests.cpp | 1 + src/wutil.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 62fbd2f11..77e646b7f 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/src/wutil.cpp b/src/wutil.cpp index 39c069afa..cbd18da94 100644 --- a/src/wutil.cpp +++ b/src/wutil.cpp @@ -705,10 +705,12 @@ unsigned long long fish_wcstoull(const wchar_t *str, const wchar_t **endptr, int double fish_wcstod(const wchar_t *str, wchar_t **endptr) { // The "fast path." If we're all ASCII and we fit inline, use strtod(). char narrow[128]; - size_t len_plus_0 = 1 + wcslen(str); - auto is_ascii = [](wchar_t c) { return c >= 0 && c <= 127; }; - if (len_plus_0 <= sizeof narrow && std::all_of(str, str + len_plus_0, is_ascii)) { + size_t len = wcslen(str); + size_t len_plus_0 = 1 + len; + auto is_digit = [](wchar_t c) { return '0' <= c && c <= '9'; }; + if (len_plus_0 <= sizeof narrow && std::all_of(str, str + len, is_digit)) { // Fast path. Copy the string into a local buffer and run strtod() on it. + // We can ignore the locale-taking version because we are limited to ASCII digits. std::copy(str, str + len_plus_0, narrow); char *narrow_endptr = nullptr; double ret = strtod(narrow, endptr ? &narrow_endptr : nullptr);