From f991b1d853560928299d8dea3885da56ad8048b6 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Thu, 16 Oct 2003 17:24:07 +0000 Subject: [PATCH] re PR libstdc++/12540 (Memory leak in locale::locale(const char*)) 2003-10-16 Paolo Carlini PR libstdc++/12540 * config/locale/gnu/monetary_members.cc (moneypunct::_M_initialize_moneypunct): Don't leak memory if new throws. * src/locale.cc (locale::locale(const char*)): In order not to leak memory in case new throws, use a basic_string type for __res too and avoid strdup. From-SVN: r72553 --- libstdc++-v3/ChangeLog | 10 + .../config/locale/gnu/monetary_members.cc | 198 ++++++++++-------- libstdc++-v3/src/locale.cc | 15 +- 3 files changed, 129 insertions(+), 94 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6b73aee7103..c53f88538f6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2003-10-16 Paolo Carlini + + PR libstdc++/12540 + * config/locale/gnu/monetary_members.cc + (moneypunct::_M_initialize_moneypunct): + Don't leak memory if new throws. + * src/locale.cc (locale::locale(const char*)): In order not + to leak memory in case new throws, use a basic_string type + for __res too and avoid strdup. + 2003-10-14 Jeff Bailey PR libstdc++/12562 diff --git a/libstdc++-v3/config/locale/gnu/monetary_members.cc b/libstdc++-v3/config/locale/gnu/monetary_members.cc index a22bdfe6f24..0c03feb66fa 100644 --- a/libstdc++-v3/config/locale/gnu/monetary_members.cc +++ b/libstdc++-v3/config/locale/gnu/monetary_members.cc @@ -379,47 +379,60 @@ namespace std const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); - mbstate_t __state; - size_t __len = strlen(__cpossign); - if (__len) + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); + try { - ++__len; - memset(&__state, 0, sizeof(mbstate_t)); - wchar_t* __wcs = new wchar_t[__len]; - mbsrtowcs(__wcs, &__cpossign, __len, &__state); - _M_data->_M_positive_sign = __wcs; + mbstate_t __state; + size_t __len = strlen(__cpossign); + if (__len) + { + ++__len; + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len]; + mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + ++__len; + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + ++__len; + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len]; + mbsrtowcs(__wcs, &__ccurr, __len, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; } - else - _M_data->_M_positive_sign = L""; - - char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); - __len = strlen(__cnegsign); - if (!__nposn) - _M_data->_M_negative_sign = L"()"; - else if (__len) - { - ++__len; - memset(&__state, 0, sizeof(mbstate_t)); - wchar_t* __wcs = new wchar_t[__len]; - mbsrtowcs(__wcs, &__cnegsign, __len, &__state); - _M_data->_M_negative_sign = __wcs; - } - else - _M_data->_M_negative_sign = L""; - - // _Intl == true. - __len = strlen(__ccurr); - if (__len) + catch (...) { - ++__len; - memset(&__state, 0, sizeof(mbstate_t)); - wchar_t* __wcs = new wchar_t[__len]; - mbsrtowcs(__wcs, &__ccurr, __len, &__state); - _M_data->_M_curr_symbol = __wcs; - } - else - _M_data->_M_curr_symbol = L""; - + delete _M_data; + _M_data = 0; + delete __wcs_ps; + delete __wcs_ns; + __throw_exception_again; + } + _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); @@ -442,18 +455,18 @@ namespace std } template<> - void - moneypunct::_M_initialize_moneypunct(__c_locale __cloc, -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) - const char*) + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc, +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) + const char*) #else - const char* __name) + const char* __name) #endif - { - if (!_M_data) - _M_data = new __moneypunct_cache; + { + if (!_M_data) + _M_data = new __moneypunct_cache; - if (!__cloc) + if (!__cloc) { // "C" locale _M_data->_M_decimal_point = L'.'; @@ -489,47 +502,60 @@ namespace std const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); - mbstate_t __state; - size_t __len; - __len = strlen(__cpossign); - if (__len) + wchar_t* __wcs_ps = 0; + wchar_t* __wcs_ns = 0; + const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); + try + { + mbstate_t __state; + size_t __len; + __len = strlen(__cpossign); + if (__len) + { + ++__len; + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ps = new wchar_t[__len]; + mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state); + _M_data->_M_positive_sign = __wcs_ps; + } + else + _M_data->_M_positive_sign = L""; + + __len = strlen(__cnegsign); + if (!__nposn) + _M_data->_M_negative_sign = L"()"; + else if (__len) + { + ++__len; + memset(&__state, 0, sizeof(mbstate_t)); + __wcs_ns = new wchar_t[__len]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state); + _M_data->_M_negative_sign = __wcs_ns; + } + else + _M_data->_M_negative_sign = L""; + + // _Intl == true. + __len = strlen(__ccurr); + if (__len) + { + ++__len; + memset(&__state, 0, sizeof(mbstate_t)); + wchar_t* __wcs = new wchar_t[__len]; + mbsrtowcs(__wcs, &__ccurr, __len, &__state); + _M_data->_M_curr_symbol = __wcs; + } + else + _M_data->_M_curr_symbol = L""; + } + catch (...) { - ++__len; - memset(&__state, 0, sizeof(mbstate_t)); - wchar_t* __wcs = new wchar_t[__len]; - mbsrtowcs(__wcs, &__cpossign, __len, &__state); - _M_data->_M_positive_sign = __wcs; + delete _M_data; + _M_data = 0; + delete __wcs_ps; + delete __wcs_ns; + __throw_exception_again; } - else - _M_data->_M_positive_sign = L""; - - char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); - __len = strlen(__cnegsign); - if (!__nposn) - _M_data->_M_negative_sign = L"()"; - else if (__len) - { - ++__len; - memset(&__state, 0, sizeof(mbstate_t)); - wchar_t* __wcs = new wchar_t[__len]; - mbsrtowcs(__wcs, &__cnegsign, __len, &__state); - _M_data->_M_negative_sign = __wcs; - } - else - _M_data->_M_negative_sign = L""; - - // _Intl == true. - __len = strlen(__ccurr); - if (__len) - { - ++__len; - memset(&__state, 0, sizeof(mbstate_t)); - wchar_t* __wcs = new wchar_t[__len]; - mbsrtowcs(__wcs, &__ccurr, __len, &__state); - _M_data->_M_curr_symbol = __wcs; - } - else - _M_data->_M_curr_symbol = L""; _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index baa5a4183d7..12f77e1997e 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -208,20 +208,20 @@ namespace std } else { - char* __res; + string __res; // LANG may set a default different from "C". char* __env = std::getenv("LANG"); if (!__env || std::strcmp(__env, "") == 0 || std::strcmp(__env, "C") == 0 || std::strcmp(__env, "POSIX") == 0) - __res = strdup("C"); + __res = "C"; else - __res = strdup(__env); + __res = __env; // Scan the categories looking for the first one // different from LANG. size_t __i = 0; - if (std::strcmp(__res, "C") == 0) + if (std::strcmp(__res.c_str(), "C") == 0) for (; __i < _S_categories_size; ++__i) { __env = std::getenv(_S_categories[__i]); @@ -235,7 +235,7 @@ namespace std { __env = std::getenv(_S_categories[__i]); if (__env && std::strcmp(__env, "") != 0 - && std::strcmp(__env, __res) != 0) + && std::strcmp(__env, __res.c_str()) != 0) break; } @@ -285,11 +285,10 @@ namespace std } // ... otherwise either an additional instance of // the "C" locale or LANG. - else if (std::strcmp(__res, "C") == 0) + else if (std::strcmp(__res.c_str(), "C") == 0) (_M_impl = _S_classic)->_M_add_reference(); else - _M_impl = new _Impl(__res, 1); - std::free(__res); + _M_impl = new _Impl(__res.c_str(), 1); } } }