From 7e4844b35371bcfd5cdff688a9d7346f8e982211 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Fri, 8 Mar 2013 19:06:24 +0000 Subject: [PATCH] Parsing floating point numbers with very long precision was broken, and this patch fixes it. This fixes http://llvm.org/bugs/show_bug.cgi?id=15445. llvm-svn: 176711 --- libcxx/include/locale | 20 +++++++++++++------- .../facet.num.get.members/get_double.pass.cpp | 12 ++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libcxx/include/locale b/libcxx/include/locale index 39aba84..8f9a3b6 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -646,6 +646,8 @@ __num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __ex _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping, unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms) { + if (__a_end-__a >= __num_get_buf_sz - 1) + return -1; if (__ct == __decimal_point) { if (!__in_units) @@ -673,23 +675,27 @@ __num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __ex char __x = __src[__f]; if (__x == '-' || __x == '+') { - if (__a_end == __a || (__a_end[-1] & 0xDF) == __exp) + if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F)) { *__a_end++ = __x; return 0; } return -1; } - if (__a_end-__a < __num_get_buf_sz - 1) - *__a_end++ = __x; if (__x == 'x' || __x == 'X') __exp = 'P'; - else if ((__x & 0xDF) == __exp) + else if ((__x & 0x5F) == __exp) { - __in_units = false; - if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz) - *__g_end++ = __dc; + __exp |= 0x80; + if (__in_units) + { + __in_units = false; + if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz) + *__g_end++ = __dc; + } } + if (__a_end-__a < __num_get_buf_sz - ((__exp & 0x80) ? 1 : 11)) + *__a_end++ = __x; if (__f >= 22) return 0; ++__dc; diff --git a/libcxx/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp b/libcxx/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp index 58c9b2d..4e0f2b8 100644 --- a/libcxx/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp +++ b/libcxx/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp @@ -240,4 +240,16 @@ int main() assert(iter.base() == str+sizeof(str)-1); assert(err == ios.failbit); } + { + v = -1; + const char str[] = "3;14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651e+10"; + std::ios_base::iostate err = ios.goodbit; + input_iterator iter = + f.get(input_iterator(str), + input_iterator(str+sizeof(str)), + ios, err, v); + assert(iter.base() == str+sizeof(str)-1); + assert(err == ios.goodbit); + assert(std::abs(v - 3.14159265358979e+10)/3.14159265358979e+10 < 1.e-8); + } } -- 2.7.4