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:
parent
8c0c83feb0
commit
5dfbc52264
1 changed files with 34 additions and 15 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue