[libcxx] r179556 - Numeric parsing was getting the wrong answer when faced with very long inputs. This fixes both http://llvm.org/bugs/show_bug.cgi?id=15751 and http://llvm.org/bugs/show_bug.cgi?id=15740

Howard Hinnant hhinnant at apple.com
Mon Apr 15 13:40:06 PDT 2013


Author: hhinnant
Date: Mon Apr 15 15:40:06 2013
New Revision: 179556

URL: http://llvm.org/viewvc/llvm-project?rev=179556&view=rev
Log:
Numeric parsing was getting the wrong answer when faced with very long inputs.  This fixes both http://llvm.org/bugs/show_bug.cgi?id=15751 and http://llvm.org/bugs/show_bug.cgi?id=15740

Modified:
    libcxx/trunk/include/locale
    libcxx/trunk/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp

Modified: libcxx/trunk/include/locale
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/locale?rev=179556&r1=179555&r2=179556&view=diff
==============================================================================
--- libcxx/trunk/include/locale (original)
+++ libcxx/trunk/include/locale Mon Apr 15 15:40:06 2013
@@ -634,8 +634,7 @@ __num_get<_CharT>::__stage2_int_loop(_Ch
         }
         return -1;
     }
-    if (__a_end-__a < __num_get_buf_sz - 1)
-        *__a_end++ = __src[__f];
+    *__a_end++ = __src[__f];
     ++__dc;
     return 0;
 }
@@ -646,8 +645,6 @@ __num_get<_CharT>::__stage2_float_loop(_
                     _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)
@@ -694,8 +691,7 @@ __num_get<_CharT>::__stage2_float_loop(_
                 *__g_end++ = __dc;
         }
     }
-    if (__a_end-__a < __num_get_buf_sz - ((__exp & 0x80) ? 1 : 11))
-        *__a_end++ = __x;
+    *__a_end++ = __x;
     if (__f >= 22)
         return 0;
     ++__dc;
@@ -975,16 +971,28 @@ num_get<_CharT, _InputIterator>::do_get(
     char_type __atoms[26];
     char_type __thousands_sep;
     string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
     unsigned __dc = 0;
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
                                     __thousands_sep, __grouping, __g, __g_end,
                                     __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1010,16 +1018,28 @@ num_get<_CharT, _InputIterator>::do_get(
     char_type __atoms[26];
     char_type __thousands_sep;
     string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
     unsigned __dc = 0;
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
                                     __thousands_sep, __grouping, __g, __g_end,
                                     __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1045,16 +1065,28 @@ num_get<_CharT, _InputIterator>::do_get(
     char_type __atoms[26];
     char_type __thousands_sep;
     string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
     unsigned __dc = 0;
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
                                     __thousands_sep, __grouping, __g, __g_end,
                                     __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1080,16 +1112,28 @@ num_get<_CharT, _InputIterator>::do_get(
     char_type __atoms[26];
     char_type __thousands_sep;
     string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
     unsigned __dc = 0;
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
                                     __thousands_sep, __grouping, __g, __g_end,
                                     __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1115,16 +1159,28 @@ num_get<_CharT, _InputIterator>::do_get(
     char_type __atoms[26];
     char_type __thousands_sep;
     string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
     unsigned __dc = 0;
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
                                     __thousands_sep, __grouping, __g, __g_end,
                                     __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1150,16 +1206,28 @@ num_get<_CharT, _InputIterator>::do_get(
     char_type __atoms[26];
     char_type __thousands_sep;
     string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
     unsigned __dc = 0;
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
                                     __thousands_sep, __grouping, __g, __g_end,
                                     __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1187,7 +1255,9 @@ num_get<_CharT, _InputIterator>::do_get(
     string __grouping = this->__stage2_float_prep(__iob, __atoms,
                                                   __decimal_point,
                                                   __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
@@ -1195,11 +1265,21 @@ num_get<_CharT, _InputIterator>::do_get(
     bool __in_units = true;
     char __exp = 'E';
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
                                       __decimal_point, __thousands_sep,
                                       __grouping, __g, __g_end,
                                       __dc, __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1227,7 +1307,9 @@ num_get<_CharT, _InputIterator>::do_get(
     string __grouping = this->__stage2_float_prep(__iob, __atoms,
                                                   __decimal_point,
                                                   __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
@@ -1235,11 +1317,21 @@ num_get<_CharT, _InputIterator>::do_get(
     bool __in_units = true;
     char __exp = 'E';
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
                                       __decimal_point, __thousands_sep,
                                       __grouping, __g, __g_end,
                                       __dc, __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1267,7 +1359,9 @@ num_get<_CharT, _InputIterator>::do_get(
     string __grouping = this->__stage2_float_prep(__iob, __atoms,
                                                   __decimal_point,
                                                   __thousands_sep);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
@@ -1275,11 +1369,21 @@ num_get<_CharT, _InputIterator>::do_get(
     bool __in_units = true;
     char __exp = 'E';
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
                                       __decimal_point, __thousands_sep,
                                       __grouping, __g, __g_end,
                                       __dc, __atoms))
             break;
+    }
     if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
         *__g_end++ = __dc;
     // Stage 3
@@ -1307,16 +1411,28 @@ num_get<_CharT, _InputIterator>::do_get(
     string __grouping;
     use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
                                                     __num_get_base::__src + 26, __atoms);
-    char __a[__num_get_base::__num_get_buf_sz] = {0};
+    string __buf;
+    __buf.resize(__buf.capacity());
+    char* __a = &__buf[0];
     char* __a_end = __a;
     unsigned __g[__num_get_base::__num_get_buf_sz];
     unsigned* __g_end = __g;
     unsigned __dc = 0;
     for (; __b != __e; ++__b)
+    {
+        if (__a_end - __a == __buf.size())
+        {
+            size_t __tmp = __buf.size();
+            __buf.resize(2*__buf.size());
+            __buf.resize(__buf.capacity());
+            __a = &__buf[0];
+            __a_end = __a + __tmp;
+        }
         if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
                                     __thousands_sep, __grouping,
                                     __g, __g_end, __atoms))
             break;
+    }
     // Stage 3
     __a[sizeof(__a)-1] = 0;
 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS

Modified: libcxx/trunk/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp?rev=179556&r1=179555&r2=179556&view=diff
==============================================================================
--- libcxx/trunk/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp (original)
+++ libcxx/trunk/test/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp Mon Apr 15 15:40:06 2013
@@ -216,4 +216,16 @@ int main()
         assert(err == ios.failbit);
         assert(v == INFINITY);
     }
+    {
+        const char str[] = "304888344611713860501504000000";
+        std::ios_base::iostate err = ios.goodbit;
+        v = 0;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err != ios.failbit);
+        assert(v == 304888344611713860501504000000.0L);
+    }
 }





More information about the cfe-commits mailing list