libstdc++: Avoid bad_alloc exceptions when changing locales

For the --enable-clocale=generic configuration, the current code can
fail with a bad_alloc exception. This patch uses the nothrow version of
operator new and reports allocation failures by setting failbit in the
iostate variable.

	* config/locale/generic/c_locale.cc (__set_C_locale()): New function
	to set the "C" locale and return the name of the previous locale.
	(__convert_to_v<float>, __convert_to_v<double>)
	(__convert_to_v<long double>): Use __set_C_locale and set failbit on
	error.
This commit is contained in:
Jonathan Wakely 2020-11-10 19:23:15 +00:00
parent 8c0c83feb0
commit 5dfbc52264
1 changed files with 34 additions and 15 deletions

View File

@ -52,6 +52,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_Save_errno() { if (errno == 0) errno = _M_errno; }
int _M_errno;
};
// calls setlocale(LC_ALL, "C") and returns a string containing the old
// locale name. Caller must delete[] the string. Returns NULL on error.
const char*
__set_C_locale()
{
char* __old = setlocale(LC_ALL, 0);
const size_t __len = strlen(__old) + 1;
char* __sav = new(nothrow) char[__len];
if (__sav)
{
memcpy(__sav, __old, __len);
setlocale(LC_ALL, "C");
}
return __sav;
}
}
template<>
@ -60,11 +76,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const __c_locale&) throw()
{
// Assumes __s formatted for "C" locale.
char* __old = setlocale(LC_ALL, 0);
const size_t __len = strlen(__old) + 1;
char* __sav = new char[__len];
memcpy(__sav, __old, __len);
setlocale(LC_ALL, "C");
const char* __sav = __set_C_locale();
if (!__sav)
{
__err = ios_base::failbit;
return;
}
char* __sanity;
bool __overflow = false;
@ -125,11 +142,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const __c_locale&) throw()
{
// Assumes __s formatted for "C" locale.
char* __old = setlocale(LC_ALL, 0);
const size_t __len = strlen(__old) + 1;
char* __sav = new char[__len];
memcpy(__sav, __old, __len);
setlocale(LC_ALL, "C");
const char* __sav = __set_C_locale();
if (!__sav)
{
__err = ios_base::failbit;
return;
}
char* __sanity;
#if !__DBL_HAS_INFINITY__
@ -170,11 +188,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
ios_base::iostate& __err, const __c_locale&) throw()
{
// Assumes __s formatted for "C" locale.
char* __old = setlocale(LC_ALL, 0);
const size_t __len = strlen(__old) + 1;
char* __sav = new char[__len];
memcpy(__sav, __old, __len);
setlocale(LC_ALL, "C");
const char* __sav = __set_C_locale();
if (!__sav)
{
__err = ios_base::failbit;
return;
}
#if !__LDBL_HAS_INFINITY__
const _Save_errno __save_errno;