[Bug libstdc++/68737] FAIL: 22_locale/num_put/put/char/14220.cc execution test
dave.anglin at bell dot net
gcc-bugzilla@gcc.gnu.org
Wed Sep 5 15:02:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68737
--- Comment #22 from dave.anglin at bell dot net ---
I prefer the first approach although it might loop if there is an
error. Probably, it needs
to check if the current __cs_size is less than the new __cs_size before
doing a retry.
Another option would be to just duplicate the code instead of branching
back.
It's my understanding that the vsnprintf bug is fixed in 11.31 and some
HP-UX patch sets.
We win with the first approach when the initial buffer is large enough.
It's possible for vsnprintf on linux to return a negative value if an
output error occurs.
So, there's some justification to check the return on linux.
On 2018-09-05 8:07 AM, redi at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68737
>
> --- Comment #21 from Jonathan Wakely <redi at gcc dot gnu.org> ---
> This should never fail:
>
> --- a/libstdc++-v3/include/bits/locale_facets.tcc
> +++ b/libstdc++-v3/include/bits/locale_facets.tcc
> @@ -1000,7 +1000,11 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
> // 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));
> + char* __cs;
> +
> +__retry_convert_from_v:
> +
> + __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);
> @@ -1020,6 +1024,15 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
> __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
> __fbuf, __v);
> }
> + else if (__builtin_expect(__len == -1, false))
> + {
> + const bool __fixed = __io.flags() & ios_base::fixed;
> + const int __max_exp =
> + __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10;
> + __cs_size = __fixed ? __max_exp + __prec + 4
> + : __max_digits * 2 + __prec;
> + goto __retry_convert_from_v;
> + }
> #else
> // Consider the possibility of long ios_base::fixed outputs
> const bool __fixed = __io.flags() & ios_base::fixed;
>
>
>
> Another option is to simply define _GLIBCXX_BROKEN_VSNPRINTF in
> config/os/hpux/os_defines.h and then force the use of vsprintf, which is always
> called with a large enough buffer:
>
> diff --git a/libstdc++-v3/config/locale/generic/c_locale.h
> b/libstdc++-v3/config/locale/generic/c_locale.h
> index 0d208166063..3045931c840 100644
> --- a/libstdc++-v3/config/locale/generic/c_locale.h
> +++ b/libstdc++-v3/config/locale/generic/c_locale.h
> @@ -70,7 +70,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> __builtin_va_list __args;
> __builtin_va_start(__args, __fmt);
>
> -#if _GLIBCXX_USE_C99_STDIO
> +#if _GLIBCXX_USE_C99_STDIO && !_GLIBCXX_HAVE_BROKEN_VSNPRINTF
> const int __ret = __builtin_vsnprintf(__out, __size, __fmt, __args);
> #else
> const int __ret = __builtin_vsprintf(__out, __fmt, __args);
> diff --git a/libstdc++-v3/config/os/hpux/os_defines.h
> b/libstdc++-v3/config/os/hpux/os_defines.h
> index 1003477fe35..5a9c4faf75d 100644
> --- a/libstdc++-v3/config/os/hpux/os_defines.h
> +++ b/libstdc++-v3/config/os/hpux/os_defines.h
> @@ -109,4 +109,9 @@ typedef long int __padding_type;
> #if defined (__hppa__)
> #define _GLIBCXX_HAVE_BROKEN_STRTOLD 1
> #endif
> +
> +// The vnsprintf function returns -1 when the buffer is too small.
> +// See PR libstdc++/68737.
> +#define _GLIBCXX_HAVE_BROKEN_VSNPRINTF 1
> +
> #endif
> diff --git a/libstdc++-v3/include/bits/locale_facets.tcc
> b/libstdc++-v3/include/bits/locale_facets.tcc
> index 39da5766075..d5fa91e97d6 100644
> --- a/libstdc++-v3/include/bits/locale_facets.tcc
> +++ b/libstdc++-v3/include/bits/locale_facets.tcc
> @@ -992,7 +992,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
> char __fbuf[16];
> __num_base::_S_format_float(__io, __fbuf, __mod);
>
> -#if _GLIBCXX_USE_C99_STDIO
> +#if _GLIBCXX_USE_C99_STDIO && !_GLIBCXX_HAVE_BROKEN_VSNPRINTF
> // Precision is always used except for hexfloat format.
> const bool __use_prec =
> (__io.flags() & ios_base::floatfield) != ios_base::floatfield;
>
More information about the Gcc-bugs
mailing list