From 39450834f7aa5787d91be55a1d64db129d663ac0 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Mon, 19 Jan 2004 00:12:55 +0000 Subject: [PATCH] re PR libstdc++/12352 (Exception safety problems in src/localename.cc) 2004-01-19 Paolo Carlini PR libstdc++/12352 PR libstdc++/12438 * include/bits/locale_classes.h (locale::locale(const locale&, _Facet*)): Don't leak memory on exception. * include/bits/locale_facets.tcc (locale::combine(const locale&)): Likewise. * src/locale.cc (locale::locale(const char*)): Likewise. * src/localename.cc (locale::_Impl::~_Impl(), locale::_Impl::_Impl(const _Impl&, size_t), locale::_Impl::_Impl(const char*, size_t)): Likewise. (locale::_Impl::_M_replace_categories(const _Impl*, category): Tweak. From-SVN: r76124 --- libstdc++-v3/ChangeLog | 15 ++ libstdc++-v3/include/bits/locale_classes.h | 32 +++- libstdc++-v3/include/bits/locale_facets.tcc | 10 +- libstdc++-v3/src/locale.cc | 15 +- libstdc++-v3/src/localename.cc | 179 +++++++++++--------- 5 files changed, 152 insertions(+), 99 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3d84488cb367..5df60196bc65 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,18 @@ +2004-01-19 Paolo Carlini + + PR libstdc++/12352 + PR libstdc++/12438 + * include/bits/locale_classes.h (locale::locale(const locale&, + _Facet*)): Don't leak memory on exception. + * include/bits/locale_facets.tcc (locale::combine(const locale&)): + Likewise. + * src/locale.cc (locale::locale(const char*)): Likewise. + * src/localename.cc (locale::_Impl::~_Impl(), + locale::_Impl::_Impl(const _Impl&, size_t), + locale::_Impl::_Impl(const char*, size_t)): Likewise. + (locale::_Impl::_M_replace_categories(const _Impl*, category): + Tweak. + 2004-01-12 Marc Espie * src/Makefile.am (version.dep): backport from HEAD. diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h index ddd23fb9726a..0a44de63661d 100644 --- a/libstdc++-v3/include/bits/locale_classes.h +++ b/libstdc++-v3/include/bits/locale_classes.h @@ -302,14 +302,32 @@ namespace std locale::locale(const locale& __other, _Facet* __f) { _M_impl = new _Impl(*__other._M_impl, 1); - _M_impl->_M_install_facet(&_Facet::id, __f); - for (size_t __i = 0; - __i < _S_categories_size + _S_extra_categories_size; ++__i) + + char* _M_tmp_names[_S_categories_size + _S_extra_categories_size]; + size_t __i = 0; + try + { + for (; __i < _S_categories_size + + _S_extra_categories_size; ++__i) + { + _M_tmp_names[__i] = new char[2]; + strcpy(_M_tmp_names[__i], "*"); + } + _M_impl->_M_install_facet(&_Facet::id, __f); + } + catch(...) + { + _M_impl->_M_remove_reference(); + for (size_t __j = 0; __j < __i; ++__j) + delete [] _M_tmp_names[__j]; + __throw_exception_again; + } + + for (size_t __k = 0; __k < _S_categories_size + + _S_extra_categories_size; ++__k) { - delete [] _M_impl->_M_names[__i]; - char* __new = new char[2]; - strcpy(__new, "*"); - _M_impl->_M_names[__i] = __new; + delete [] _M_impl->_M_names[__k]; + _M_impl->_M_names[__k] = _M_tmp_names[__k]; } } diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 2563a9595d1d..f2a1ce04d23c 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -51,7 +51,15 @@ namespace std locale::combine(const locale& __other) const { _Impl* __tmp = new _Impl(*_M_impl, 1); - __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); + try + { + __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); + } + catch(...) + { + __tmp->_M_remove_reference(); + __throw_exception_again; + } return locale(__tmp); } diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 17ccdc2e4c68..745327591816 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -194,19 +194,19 @@ namespace std } else { - char* __res; + string __res; // LANG may set a default different from "C". char* __env = getenv("LANG"); if (!__env || strcmp(__env, "") == 0 || strcmp(__env, "C") == 0 || 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 (strcmp(__res, "C") == 0) + if (__res == "C") for (; __i < _S_categories_size + _S_extra_categories_size; ++__i) { @@ -222,7 +222,7 @@ namespace std { __env = getenv(_S_categories[__i]); if (__env && strcmp(__env, "") != 0 - && strcmp(__env, __res) != 0) + && __res != __env) break; } @@ -273,11 +273,10 @@ namespace std } // ... otherwise either an additional instance of // the "C" locale or LANG. - else if (strcmp(__res, "C") == 0) + else if (__res == "C") (_M_impl = _S_classic)->_M_add_reference(); else - _M_impl = new _Impl(__res, 1); - free(__res); + _M_impl = new _Impl(__res.c_str(), 1); } } } diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc index ec35fdb1eaa0..38311fb64f7b 100644 --- a/libstdc++-v3/src/localename.cc +++ b/libstdc++-v3/src/localename.cc @@ -84,17 +84,21 @@ namespace std ~_Impl() throw() { // Clean up facets, then caches. No cache refcounts for now. - for (size_t __i = 0; __i < _M_facets_size; ++__i) - if (_M_facets[__i]) - _M_facets[__i]->_M_remove_reference(); - for (size_t __i = _M_facets_size; __i < 2*_M_facets_size; ++__i) - if (_M_facets[__i]) - delete (__locale_cache_base*)_M_facets[__i]; + if (_M_facets) + { + for (size_t __i = 0; __i < _M_facets_size; ++__i) + if (_M_facets[__i]) + _M_facets[__i]->_M_remove_reference(); + + for (size_t __i = _M_facets_size; __i < 2*_M_facets_size; ++__i) + if (_M_facets[__i]) + delete (__locale_cache_base*)_M_facets[__i]; + } delete [] _M_facets; for (size_t __i = 0; __i < _S_categories_size + _S_extra_categories_size; ++__i) - delete [] _M_names[__i]; + delete [] _M_names[__i]; } // Clone existing _Impl object. @@ -102,30 +106,34 @@ namespace std _Impl(const _Impl& __imp, size_t __refs) : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX { + _M_facets = 0; + for (size_t __i = 0; __i < _S_categories_size + + _S_extra_categories_size; ++__i) + _M_names[__i] = 0; try { // Space for facets and matching caches _M_facets = new facet*[2*_M_facets_size]; for (size_t __i = 0; __i < 2*_M_facets_size; ++__i) _M_facets[__i] = 0; + for (size_t __i = 0; __i < _M_facets_size; ++__i) + { + _M_facets[__i] = __imp._M_facets[__i]; + if (_M_facets[__i]) + _M_facets[__i]->_M_add_reference(); + } + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + char* __new = new char[strlen(__imp._M_names[__i]) + 1]; + strcpy(__new, __imp._M_names[__i]); + _M_names[__i] = __new; + } } - catch(...) - { - delete [] _M_facets; - __throw_exception_again; - } - for (size_t __i = 0; __i < _M_facets_size; ++__i) - { - _M_facets[__i] = __imp._M_facets[__i]; - if (_M_facets[__i]) - _M_facets[__i]->_M_add_reference(); - } - for (size_t __i = 0; - __i < _S_categories_size + _S_extra_categories_size; ++__i) + catch(...) { - char* __new = new char[strlen(__imp._M_names[__i]) + 1]; - strcpy(__new, __imp._M_names[__i]); - _M_names[__i] = __new; + this->~_Impl(); + __throw_exception_again; } } @@ -139,80 +147,85 @@ namespace std __c_locale __cloc; locale::facet::_S_create_c_locale(__cloc, __s); + _M_facets = 0; + for (size_t __i = 0; __i < _S_categories_size + + _S_extra_categories_size; ++__i) + _M_names[__i] = 0; try { // Space for facets and matching caches _M_facets = new facet*[2*_M_facets_size]; for (size_t __i = 0; __i < 2*_M_facets_size; ++__i) _M_facets[__i] = 0; - } - catch(...) - { - delete [] _M_facets; - __throw_exception_again; - } - // Name all the categories. - size_t __len = strlen(__s); - if (!strchr(__s, ';')) - { - for (size_t __i = 0; - __i < _S_categories_size + _S_extra_categories_size; ++__i) + // Name all the categories. + size_t __len = strlen(__s); + if (!strchr(__s, ';')) { - _M_names[__i] = new char[__len + 1]; - strcpy(_M_names[__i], __s); + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + _M_names[__i] = new char[__len + 1]; + strcpy(_M_names[__i], __s); + } } - } - else - { - const char* __beg = __s; - for (size_t __i = 0; - __i < _S_categories_size + _S_extra_categories_size; ++__i) + else { - __beg = strchr(__beg, '=') + 1; - const char* __end = strchr(__beg, ';'); - if (!__end) - __end = __s + __len; - char* __new = new char[__end - __beg + 1]; - memcpy(__new, __beg, __end - __beg); - __new[__end - __beg] = '\0'; - _M_names[__i] = __new; + const char* __beg = __s; + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + __beg = strchr(__beg, '=') + 1; + const char* __end = strchr(__beg, ';'); + if (!__end) + __end = __s + __len; + char* __new = new char[__end - __beg + 1]; + memcpy(__new, __beg, __end - __beg); + __new[__end - __beg] = '\0'; + _M_names[__i] = __new; + } } - } - // Construct all standard facets and add them to _M_facets. - _M_init_facet(new std::ctype(__cloc, 0, false)); - _M_init_facet(new codecvt); - _M_init_facet(new numpunct(__cloc)); - _M_init_facet(new num_get); - _M_init_facet(new num_put); - _M_init_facet(new std::collate(__cloc)); - _M_init_facet(new moneypunct(__cloc, __s)); - _M_init_facet(new moneypunct(__cloc, __s)); - _M_init_facet(new money_get); - _M_init_facet(new money_put); - _M_init_facet(new __timepunct(__cloc, __s)); - _M_init_facet(new time_get); - _M_init_facet(new time_put); - _M_init_facet(new std::messages(__cloc, __s)); + // Construct all standard facets and add them to _M_facets. + _M_init_facet(new std::ctype(__cloc, 0, false)); + _M_init_facet(new codecvt); + _M_init_facet(new numpunct(__cloc)); + _M_init_facet(new num_get); + _M_init_facet(new num_put); + _M_init_facet(new std::collate(__cloc)); + _M_init_facet(new moneypunct(__cloc, __s)); + _M_init_facet(new moneypunct(__cloc, __s)); + _M_init_facet(new money_get); + _M_init_facet(new money_put); + _M_init_facet(new __timepunct(__cloc, __s)); + _M_init_facet(new time_get); + _M_init_facet(new time_put); + _M_init_facet(new std::messages(__cloc, __s)); #ifdef _GLIBCPP_USE_WCHAR_T - _M_init_facet(new std::ctype(__cloc)); - _M_init_facet(new codecvt); - _M_init_facet(new numpunct(__cloc)); - _M_init_facet(new num_get); - _M_init_facet(new num_put); - _M_init_facet(new std::collate(__cloc)); - _M_init_facet(new moneypunct(__cloc, __s)); - _M_init_facet(new moneypunct(__cloc, __s)); - _M_init_facet(new money_get); - _M_init_facet(new money_put); - _M_init_facet(new __timepunct(__cloc, __s)); - _M_init_facet(new time_get); - _M_init_facet(new time_put); - _M_init_facet(new std::messages(__cloc, __s)); + _M_init_facet(new std::ctype(__cloc)); + _M_init_facet(new codecvt); + _M_init_facet(new numpunct(__cloc)); + _M_init_facet(new num_get); + _M_init_facet(new num_put); + _M_init_facet(new std::collate(__cloc)); + _M_init_facet(new moneypunct(__cloc, __s)); + _M_init_facet(new moneypunct(__cloc, __s)); + _M_init_facet(new money_get); + _M_init_facet(new money_put); + _M_init_facet(new __timepunct(__cloc, __s)); + _M_init_facet(new time_get); + _M_init_facet(new time_put); + _M_init_facet(new std::messages(__cloc, __s)); #endif - locale::facet::_S_destroy_c_locale(__cloc); + locale::facet::_S_destroy_c_locale(__cloc); + } + catch(...) + { + locale::facet::_S_destroy_c_locale(__cloc); + this->~_Impl(); + __throw_exception_again; + } } // Construct "C" _Impl. @@ -313,9 +326,9 @@ namespace std if (strcmp(_M_names[__ix], "*") != 0 && strcmp(__imp->_M_names[__ix], "*") != 0) { - delete [] _M_names[__ix]; char* __new = new char[strlen(__imp->_M_names[__ix]) + 1]; strcpy(__new, __imp->_M_names[__ix]); + delete [] _M_names[__ix]; _M_names[__ix] = __new; } } -- 2.47.2