https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68737

--- Comment #15 from dave.anglin at bell dot net ---
On 2018-09-04 4:51 AM, redi at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68737
>
> --- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
> And the previous line an alloca call using __len:
>
>          _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
>                                                               * __len));
>          __ctype.widen(__cs, __cs + __len, __ws);
>
>
> The code assumes __convert_from_v always returns a valid length, but it seems
> to be failing and returning -1.
It appears to me we are using the first hunk of the #if:

#if _GLIBCXX_USE_C99_STDIO
         // Precision is always used except for hexfloat format.
         const bool __use_prec =
           (__io.flags() & ios_base::floatfield) != ios_base::floatfield;

         // First try a buffer perhaps big enough (most probably sufficient
         // for non-ios_base::fixed outputs)
         int __cs_size = __max_digits * 3;
         char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
         if (__use_prec)
           __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
                                         __fbuf, __prec, __v);
         else
           __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
                                         __fbuf, __v);

         // If the buffer was not large enough, try again with the 
correct size.
         if (__len >= __cs_size)
           {
             __cs_size = __len + 1;
             __cs = static_cast<char*>(__builtin_alloca(__cs_size));
             if (__use_prec)
               __len = std::__convert_from_v(_S_get_c_locale(), __cs, 
__cs_size,
                                             __fbuf, __prec, __v);
             else
               __len = std::__convert_from_v(_S_get_c_locale(), __cs, 
__cs_size,
                                             __fbuf, __v);
           }
#else
         // Consider the possibility of long ios_base::fixed outputs
         const bool __fixed = __io.flags() & ios_base::fixed;
         const int __max_exp =
__gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10;

         // The size of the output string is computed as follows.
         // ios_base::fixed outputs may need up to __max_exp + 1 chars
         // for the integer part + __prec chars for the fractional part
         // + 3 chars for sign, decimal point, '\0'. On the other hand,
         // for non-fixed outputs __max_digits * 2 + __prec chars are
         // largely sufficient.
         const int __cs_size = __fixed ? __max_exp + __prec + 4
                                       : __max_digits * 2 + __prec;
         char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
         __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf,
                                       __prec, __v);
#endif

In the first hunk, __cs_size is not zero but __max_digits * 3.  If the 
buffer is too small,
__len will be -1.  We need to check for -1 in second if.  Is 
incrementing __cs_size by
1 enough?

Reply via email to