From 5dfbc52264fc64db22e75f385be9efae3d0eba46 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 10 Nov 2020 19:23:15 +0000 Subject: [PATCH] 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, __convert_to_v) (__convert_to_v): Use __set_C_locale and set failbit on error. --- .../config/locale/generic/c_locale.cc | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/libstdc++-v3/config/locale/generic/c_locale.cc b/libstdc++-v3/config/locale/generic/c_locale.cc index 61ead91ec1e..648b8e182cc 100644 --- a/libstdc++-v3/config/locale/generic/c_locale.cc +++ b/libstdc++-v3/config/locale/generic/c_locale.cc @@ -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; -- 2.30.2