From af90c8c9ae3b795f28cabd9f11e9f7c9a1ccccb4 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Sat, 18 Jul 2009 22:58:10 +0000 Subject: [PATCH] re PR libstdc++/40712 (locale(const locale&, const char*, locale::category) can create broken locale) 2009-07-18 Paolo Carlini PR libstdc++/40712 * config/locale/gnu/numeric_members.cc (numpunct<>:: _M_initialize_numpunct): Dynamically allocate _M_data->_M_grouping and copy the langinfo data into it. (numpunct<>::~numpunct): Free the allocated memory. * config/locale/gnu/monetary_members.cc (moneypunct<>:: _M_initialize_moneypunct): Dynamically allocate _M_data->_M_grouping, _M_data->_M_positive_sign, _M_data->_M_negative_sign, _M_data->_M_curr_symbol. (moneypunct<>::~moneypunct): Free the allocated memory. * testsuite/22_locale/moneypunct/40712.cc: New. * include/bits/locale_facets.tcc (__numpunct_cache<>::_M_cache): Do not leak memory if new throws. * include/bits/locale_facets_nonio.tcc (__moneypunct_cache<>::_M_cache): Likewise. From-SVN: r149782 --- libstdc++-v3/ChangeLog | 19 + .../config/locale/gnu/monetary_members.cc | 421 +++++++++++++----- .../config/locale/gnu/numeric_members.cc | 62 ++- libstdc++-v3/include/bits/locale_facets.tcc | 61 ++- .../include/bits/locale_facets_nonio.tcc | 73 +-- .../testsuite/22_locale/moneypunct/40712.cc | 41 ++ 6 files changed, 498 insertions(+), 179 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/moneypunct/40712.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4beeae38e62..c769be5a283 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2009-07-18 Paolo Carlini + + PR libstdc++/40712 + * config/locale/gnu/numeric_members.cc (numpunct<>:: + _M_initialize_numpunct): Dynamically allocate _M_data->_M_grouping + and copy the langinfo data into it. + (numpunct<>::~numpunct): Free the allocated memory. + * config/locale/gnu/monetary_members.cc (moneypunct<>:: + _M_initialize_moneypunct): Dynamically allocate _M_data->_M_grouping, + _M_data->_M_positive_sign, _M_data->_M_negative_sign, + _M_data->_M_curr_symbol. + (moneypunct<>::~moneypunct): Free the allocated memory. + * testsuite/22_locale/moneypunct/40712.cc: New. + + * include/bits/locale_facets.tcc (__numpunct_cache<>::_M_cache): + Do not leak memory if new throws. + * include/bits/locale_facets_nonio.tcc + (__moneypunct_cache<>::_M_cache): Likewise. + 2009-07-17 Joseph Myers PR other/40784 diff --git a/libstdc++-v3/config/locale/gnu/monetary_members.cc b/libstdc++-v3/config/locale/gnu/monetary_members.cc index c5ec8575391..02e48240ba9 100644 --- a/libstdc++-v3/config/locale/gnu/monetary_members.cc +++ b/libstdc++-v3/config/locale/gnu/monetary_members.cc @@ -236,23 +236,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __cloc)); _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); - _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); - _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign); - - // Check for NULL, which implies no grouping. - if (_M_data->_M_thousands_sep == '\0') - { - // Like in "C" locale. - _M_data->_M_grouping = ""; - _M_data->_M_grouping_size = 0; - _M_data->_M_use_grouping = false; - _M_data->_M_thousands_sep = ','; - } - else - { - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); - } // Check for NULL, which implies no fractional digits. if (_M_data->_M_decimal_point == '\0') @@ -265,25 +248,104 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); - char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); - if (!__nposn) - _M_data->_M_negative_sign = "()"; - else - _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, - __cloc); - _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign); - + const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); + const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); + const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); // _Intl == true - _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); - _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol); + const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + } + char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); - _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); - _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); } } @@ -324,23 +386,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __cloc)); _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); - _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); - _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign); - - // Check for NULL, which implies no grouping. - if (_M_data->_M_thousands_sep == '\0') - { - // Like in "C" locale. - _M_data->_M_grouping = ""; - _M_data->_M_grouping_size = 0; - _M_data->_M_use_grouping = false; - _M_data->_M_thousands_sep = ','; - } - else - { - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); - } // Check for NULL, which implies no fractional digits. if (_M_data->_M_decimal_point == '\0') @@ -353,36 +398,137 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); - char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); - if (!__nposn) - _M_data->_M_negative_sign = "()"; - else - _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, - __cloc); - _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign); - + const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); + const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); + const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); // _Intl == false - _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); - _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol); + const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); + + char* __group = 0; + char* __ps = 0; + char* __ns = 0; + const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); + __try + { + size_t __len; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == '\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = ','; + } + else + { + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + + __len = strlen(__cpossign); + if (__len) + { + __ps = new char[__len + 1]; + memcpy(__ps, __cpossign, __len + 1); + _M_data->_M_positive_sign = __ps; + } + else + _M_data->_M_positive_sign = ""; + _M_data->_M_positive_sign_size = __len; + + if (!__nposn) + { + _M_data->_M_negative_sign = "()"; + _M_data->_M_negative_sign_size = 2; + } + else + { + __len = strlen(__cnegsign); + if (__len) + { + __ns = new char[__len + 1]; + memcpy(__ns, __cnegsign, __len + 1); + _M_data->_M_negative_sign = __ns; + } + else + _M_data->_M_negative_sign = ""; + _M_data->_M_negative_sign_size = __len; + } + + __len = strlen(__ccurr); + if (__len) + { + char* __curr = new char[__len + 1]; + memcpy(__curr, __ccurr, __len + 1); + _M_data->_M_curr_symbol = __curr; + } + else + _M_data->_M_curr_symbol = ""; + _M_data->_M_curr_symbol_size = __len; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + delete [] __group; + delete [] __ps; + delete [] __ns; + } + char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); - _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); - _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); } } template<> moneypunct::~moneypunct() - { delete _M_data; } + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } template<> moneypunct::~moneypunct() - { delete _M_data; } + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + if (_M_data->_M_positive_sign_size) + delete [] _M_data->_M_positive_sign; + if (_M_data->_M_negative_sign_size + && strcmp(_M_data->_M_negative_sign, "()") != 0) + delete [] _M_data->_M_negative_sign; + if (_M_data->_M_curr_symbol_size) + delete [] _M_data->_M_curr_symbol; + delete _M_data; + } #ifdef _GLIBCXX_USE_WCHAR_T template<> @@ -441,21 +587,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); _M_data->_M_thousands_sep = __u.__w; - // Check for NULL, which implies no grouping. - if (_M_data->_M_thousands_sep == L'\0') - { - // Like in "C" locale. - _M_data->_M_grouping = ""; - _M_data->_M_grouping_size = 0; - _M_data->_M_use_grouping = false; - _M_data->_M_thousands_sep = L','; - } - else - { - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); - } - // Check for NULL, which implies no fractional digits. if (_M_data->_M_decimal_point == L'\0') { @@ -467,52 +598,81 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); + const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); + char* __group = 0; wchar_t* __wcs_ps = 0; wchar_t* __wcs_ns = 0; const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); __try { + size_t __len; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == L'\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + mbstate_t __state; - size_t __len = strlen(__cpossign); + __len = strlen(__cpossign); if (__len) { - ++__len; memset(&__state, 0, sizeof(mbstate_t)); - __wcs_ps = new wchar_t[__len]; - mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); _M_data->_M_positive_sign = __wcs_ps; } else _M_data->_M_positive_sign = L""; - _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign); + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); __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); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); _M_data->_M_negative_sign = __wcs_ns; } else _M_data->_M_negative_sign = L""; - _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign); + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); // _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); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); _M_data->_M_curr_symbol = __wcs; } else @@ -523,6 +683,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { delete _M_data; _M_data = 0; + delete [] __group; delete [] __wcs_ps; delete [] __wcs_ns; #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) @@ -537,11 +698,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); - _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); - _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) @@ -609,21 +770,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); _M_data->_M_thousands_sep = __u.__w; - // Check for NULL, which implies no grouping. - if (_M_data->_M_thousands_sep == L'\0') - { - // Like in "C" locale. - _M_data->_M_grouping = ""; - _M_data->_M_grouping_size = 0; - _M_data->_M_use_grouping = false; - _M_data->_M_thousands_sep = L','; - } - else - { - _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); - } - // Check for NULL, which implies no fractional digits. if (_M_data->_M_decimal_point == L'\0') { @@ -635,53 +781,81 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); + const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); + char* __group = 0; wchar_t* __wcs_ps = 0; wchar_t* __wcs_ns = 0; const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); __try { + size_t __len; + + // Check for NULL, which implies no grouping. + if (_M_data->_M_thousands_sep == L'\0') + { + // Like in "C" locale. + _M_data->_M_grouping = ""; + _M_data->_M_grouping_size = 0; + _M_data->_M_use_grouping = false; + _M_data->_M_thousands_sep = L','; + } + else + { + __len = strlen(__cgroup); + if (__len) + { + __group = new char[__len + 1]; + memcpy(__group, __cgroup, __len + 1); + _M_data->_M_grouping = __group; + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; + } + 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); + __wcs_ps = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); _M_data->_M_positive_sign = __wcs_ps; } else _M_data->_M_positive_sign = L""; - _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign); - + _M_data->_M_positive_sign_size = + wcslen(_M_data->_M_positive_sign); + __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); + __wcs_ns = new wchar_t[__len + 1]; + mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); _M_data->_M_negative_sign = __wcs_ns; } else _M_data->_M_negative_sign = L""; - _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign); + _M_data->_M_negative_sign_size = + wcslen(_M_data->_M_negative_sign); // _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); + wchar_t* __wcs = new wchar_t[__len + 1]; + mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); _M_data->_M_curr_symbol = __wcs; } else @@ -692,6 +866,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { delete _M_data; _M_data = 0; + delete [] __group; delete [] __wcs_ps; delete [] __wcs_ns; #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) @@ -706,11 +881,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); - _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, + _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); - _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, + _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) @@ -725,6 +900,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<> moneypunct::~moneypunct() { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; if (_M_data->_M_positive_sign_size) delete [] _M_data->_M_positive_sign; if (_M_data->_M_negative_sign_size @@ -738,6 +915,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<> moneypunct::~moneypunct() { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; if (_M_data->_M_positive_sign_size) delete [] _M_data->_M_positive_sign; if (_M_data->_M_negative_sign_size diff --git a/libstdc++-v3/config/locale/gnu/numeric_members.cc b/libstdc++-v3/config/locale/gnu/numeric_members.cc index 769c47f9ff5..637cd59b711 100644 --- a/libstdc++-v3/config/locale/gnu/numeric_members.cc +++ b/libstdc++-v3/config/locale/gnu/numeric_members.cc @@ -76,8 +76,29 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } else { - _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + const char* __src = __nl_langinfo_l(GROUPING, __cloc); + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; } } @@ -92,7 +113,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<> numpunct::~numpunct() - { delete _M_data; } + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } #ifdef _GLIBCXX_USE_WCHAR_T template<> @@ -143,8 +168,29 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } else { - _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc); - _M_data->_M_grouping_size = strlen(_M_data->_M_grouping); + const char* __src = __nl_langinfo_l(GROUPING, __cloc); + const size_t __len = strlen(__src); + if (__len) + { + __try + { + char* __dst = new char[__len + 1]; + memcpy(__dst, __src, __len + 1); + _M_data->_M_grouping = __dst; + } + __catch(...) + { + delete _M_data; + _M_data = 0; + __throw_exception_again; + } + } + else + { + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + } + _M_data->_M_grouping_size = __len; } } @@ -159,7 +205,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<> numpunct::~numpunct() - { delete _M_data; } + { + if (_M_data->_M_grouping_size) + delete [] _M_data->_M_grouping; + delete _M_data; + } #endif _GLIBCXX_END_NAMESPACE diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 85b4ec646bb..1608e2c42da 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -81,33 +81,48 @@ _GLIBCXX_BEGIN_NAMESPACE(std) const numpunct<_CharT>& __np = use_facet >(__loc); - _M_grouping_size = __np.grouping().size(); - char* __grouping = new char[_M_grouping_size]; - __np.grouping().copy(__grouping, _M_grouping_size); - _M_grouping = __grouping; - _M_use_grouping = (_M_grouping_size - && static_cast(_M_grouping[0]) > 0 - && (_M_grouping[0] - != __gnu_cxx::__numeric_traits::__max)); + char* __grouping = 0; + _CharT* __truename = 0; + _CharT* __falsename = 0; + __try + { + _M_grouping_size = __np.grouping().size(); + __grouping = new char[_M_grouping_size]; + __np.grouping().copy(__grouping, _M_grouping_size); + _M_grouping = __grouping; + _M_use_grouping = (_M_grouping_size + && static_cast(_M_grouping[0]) > 0 + && (_M_grouping[0] + != __gnu_cxx::__numeric_traits::__max)); - _M_truename_size = __np.truename().size(); - _CharT* __truename = new _CharT[_M_truename_size]; - __np.truename().copy(__truename, _M_truename_size); - _M_truename = __truename; + _M_truename_size = __np.truename().size(); + __truename = new _CharT[_M_truename_size]; + __np.truename().copy(__truename, _M_truename_size); + _M_truename = __truename; - _M_falsename_size = __np.falsename().size(); - _CharT* __falsename = new _CharT[_M_falsename_size]; - __np.falsename().copy(__falsename, _M_falsename_size); - _M_falsename = __falsename; + _M_falsename_size = __np.falsename().size(); + __falsename = new _CharT[_M_falsename_size]; + __np.falsename().copy(__falsename, _M_falsename_size); + _M_falsename = __falsename; - _M_decimal_point = __np.decimal_point(); - _M_thousands_sep = __np.thousands_sep(); + _M_decimal_point = __np.decimal_point(); + _M_thousands_sep = __np.thousands_sep(); - const ctype<_CharT>& __ct = use_facet >(__loc); - __ct.widen(__num_base::_S_atoms_out, - __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out); - __ct.widen(__num_base::_S_atoms_in, - __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in); + const ctype<_CharT>& __ct = use_facet >(__loc); + __ct.widen(__num_base::_S_atoms_out, + __num_base::_S_atoms_out + + __num_base::_S_oend, _M_atoms_out); + __ct.widen(__num_base::_S_atoms_in, + __num_base::_S_atoms_in + + __num_base::_S_iend, _M_atoms_in); + } + __catch(...) + { + delete [] __grouping; + delete [] __truename; + delete [] __falsename; + __throw_exception_again; + } } // Used by both numeric and monetary facets. diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc index 06bbfcf4447..96feeafc759 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc +++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc @@ -71,40 +71,55 @@ _GLIBCXX_BEGIN_NAMESPACE(std) const moneypunct<_CharT, _Intl>& __mp = use_facet >(__loc); - _M_grouping_size = __mp.grouping().size(); - char* __grouping = new char[_M_grouping_size]; - __mp.grouping().copy(__grouping, _M_grouping_size); - _M_grouping = __grouping; - _M_use_grouping = (_M_grouping_size - && static_cast(_M_grouping[0]) > 0 - && (_M_grouping[0] - != __gnu_cxx::__numeric_traits::__max)); - _M_decimal_point = __mp.decimal_point(); _M_thousands_sep = __mp.thousands_sep(); _M_frac_digits = __mp.frac_digits(); - - _M_curr_symbol_size = __mp.curr_symbol().size(); - _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size]; - __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size); - _M_curr_symbol = __curr_symbol; - - _M_positive_sign_size = __mp.positive_sign().size(); - _CharT* __positive_sign = new _CharT[_M_positive_sign_size]; - __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size); - _M_positive_sign = __positive_sign; - _M_negative_sign_size = __mp.negative_sign().size(); - _CharT* __negative_sign = new _CharT[_M_negative_sign_size]; - __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size); - _M_negative_sign = __negative_sign; - - _M_pos_format = __mp.pos_format(); - _M_neg_format = __mp.neg_format(); + char* __grouping = 0; + _CharT* __curr_symbol = 0; + _CharT* __positive_sign = 0; + _CharT* __negative_sign = 0; + __try + { + _M_grouping_size = __mp.grouping().size(); + __grouping = new char[_M_grouping_size]; + __mp.grouping().copy(__grouping, _M_grouping_size); + _M_grouping = __grouping; + _M_use_grouping = (_M_grouping_size + && static_cast(_M_grouping[0]) > 0 + && (_M_grouping[0] + != __gnu_cxx::__numeric_traits::__max)); - const ctype<_CharT>& __ct = use_facet >(__loc); - __ct.widen(money_base::_S_atoms, - money_base::_S_atoms + money_base::_S_end, _M_atoms); + _M_curr_symbol_size = __mp.curr_symbol().size(); + __curr_symbol = new _CharT[_M_curr_symbol_size]; + __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size); + _M_curr_symbol = __curr_symbol; + + _M_positive_sign_size = __mp.positive_sign().size(); + __positive_sign = new _CharT[_M_positive_sign_size]; + __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size); + _M_positive_sign = __positive_sign; + + _M_negative_sign_size = __mp.negative_sign().size(); + __negative_sign = new _CharT[_M_negative_sign_size]; + __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size); + _M_negative_sign = __negative_sign; + + _M_pos_format = __mp.pos_format(); + _M_neg_format = __mp.neg_format(); + + const ctype<_CharT>& __ct = use_facet >(__loc); + __ct.widen(money_base::_S_atoms, + money_base::_S_atoms + money_base::_S_end, _M_atoms); + } + __catch(...) + { + delete [] __grouping; + delete [] __curr_symbol; + delete [] __positive_sign; + delete [] __negative_sign; + __throw_exception_again; + } } _GLIBCXX_BEGIN_LDBL_NAMESPACE diff --git a/libstdc++-v3/testsuite/22_locale/moneypunct/40712.cc b/libstdc++-v3/testsuite/22_locale/moneypunct/40712.cc new file mode 100644 index 00000000000..49eb21c0f92 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/moneypunct/40712.cc @@ -0,0 +1,41 @@ +// { dg-require-namedlocale "" } + +// 2009-07-18 Paolo Carlini + +// Copyright (C) 2009 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 22.2.6.3 Template class moneypunct + +#include + +// libstdc++/40712 +void test01() +{ + bool test __attribute__((unused)) = true; + using namespace std; + + locale loc(locale("C"), "en_US", locale::monetary); + + use_facet >(loc).grouping(); +} + +int main() +{ + test01(); + return 0; +}