This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Fix libstdc++/12352
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: libstdc++ at gcc dot gnu dot org
- Cc: Benjamin Kosnik <bkoz at redhat dot com>
- Date: Thu, 25 Sep 2003 15:36:37 +0200
- Subject: [Patch] Fix libstdc++/12352
Hi,
the below doesn't hope to fix all the exception safety problems in
localename.cc (i.e., do we want the *strong* exception safety
guarantee, eventually?) but seems to me a definite improvement, fixes
the testcase and variants, ans it's already quite big as is.
Tested x86-linux. Do you like it?
In case, I promise to study in more detail these issues in the next
monts: I'm afraid Tom Cargill wouldn't happy with our past stance wrt
exception safety ;)
Paolo.
////////////
2003-09-25 Paolo Carlini <pcarlini@unitus.it>
PR libstdc++/12352
* src/localename.cc (locale::_Impl::_Impl(const _Impl&,
size_t)): Don't leak in memory allocations for _M_facets,
_M_caches, and _M_names fail.
(locale::_Impl::_Impl(const char*, size_t)): Ditto.
(locale::_Impl::_Impl(facet**, size_t, bool)): Ditto.
(locale::_Impl::_M_replace_categories(const _Impl*,
category)): Ditto.
(locale::_Impl::_M_install_facet(const locale::id*,
const facet*)): Ditto.
* include/bits/locale_classes.h (locale::locale(const locale&,
_Facet*)): Don't leak memory.
* testsuite/22_locale/locale/cons/12352.cc: New, from the PR.
* include/bits/locale_classes.h
(locale::_Impl::_M_check_same_name): Qualify strcmp.
(locale::_Impl::_Impl(facet**, size_t, bool)): Ditto for strcpy.
diff -prN libstdc++-v3-orig/include/bits/locale_classes.h libstdc++-v3/include/bits/locale_classes.h
*** libstdc++-v3-orig/include/bits/locale_classes.h Thu Jul 10 08:21:11 2003
--- libstdc++-v3/include/bits/locale_classes.h Thu Sep 25 01:07:24 2003
*************** namespace std
*** 346,352 ****
{
bool __ret = true;
for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
! __ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
return __ret;
}
--- 346,352 ----
{
bool __ret = true;
for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
! __ret &= (std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
return __ret;
}
*************** namespace std
*** 379,391 ****
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; ++__i)
{
! delete [] _M_impl->_M_names[__i];
! char* __new = new char[2];
! std::strcpy(__new, "*");
! _M_impl->_M_names[__i] = __new;
}
}
} // namespace std
--- 379,408 ----
locale::locale(const locale& __other, _Facet* __f)
{
_M_impl = new _Impl(*__other._M_impl, 1);
!
! char* _M_tmp_names[_S_categories_size];
! size_t __i = 0;
! try
! {
! for (; __i < _S_categories_size; ++__i)
! {
! _M_tmp_names[__i] = new char[2];
! std::strcpy(_M_tmp_names[__i], "*");
! }
! _M_impl->_M_install_facet(&_Facet::id, __f);
! }
! catch(...)
! {
! delete _M_impl;
! 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; ++__k)
{
! delete [] _M_impl->_M_names[__k];
! _M_impl->_M_names[__k] = _M_tmp_names[__k];
}
}
} // namespace std
diff -prN libstdc++-v3-orig/src/localename.cc libstdc++-v3/src/localename.cc
*** libstdc++-v3-orig/src/localename.cc Fri Jul 18 04:27:16 2003
--- libstdc++-v3/src/localename.cc Thu Sep 25 13:36:04 2003
*************** namespace __gnu_cxx
*** 44,50 ****
extern numpunct<char> numpunct_c;
extern num_get<char> num_get_c;
extern num_put<char> num_put_c;
! extern codecvt<char, char, mbstate_t> codecvt_c;
extern moneypunct<char, false> moneypunct_cf;
extern moneypunct<char, true> moneypunct_ct;
extern money_get<char> money_get_c;
--- 44,50 ----
extern numpunct<char> numpunct_c;
extern num_get<char> num_get_c;
extern num_put<char> num_put_c;
! extern codecvt<char, char, mbstate_t> codecvt_c;
extern moneypunct<char, false> moneypunct_cf;
extern moneypunct<char, true> moneypunct_ct;
extern money_get<char> money_get_c;
*************** namespace std
*** 111,165 ****
_Impl(const _Impl& __imp, size_t __refs)
: _M_references(__refs), _M_facets_size(__imp._M_facets_size)
{
try
! {
_M_facets = new const facet*[_M_facets_size];
! for (size_t __i = 0; __i < _M_facets_size; ++__i)
! _M_facets[__i] = 0;
}
! 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();
- }
-
- try
- {
- _M_caches = new const facet*[_M_facets_size];
- }
- catch(...)
- {
- delete [] _M_caches;
- __throw_exception_again;
- }
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- {
- _M_caches[__i] = __imp._M_caches[__i];
if (_M_caches[__i])
! _M_caches[__i]->_M_add_reference();
}
! try
{
! _M_names = new char*[_S_categories_size];
}
catch(...)
{
! delete [] _M_names;
__throw_exception_again;
}
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
- {
- char* __new = new char[strlen(__imp._M_names[__i]) + 1];
- std::strcpy(__new, __imp._M_names[__i]);
- _M_names[__i] = __new;
- }
}
// Construct named _Impl.
--- 111,158 ----
_Impl(const _Impl& __imp, size_t __refs)
: _M_references(__refs), _M_facets_size(__imp._M_facets_size)
{
+ _M_facets = _M_caches = 0;
+ _M_names = 0;
try
! {
_M_facets = new const facet*[_M_facets_size];
! _M_caches = new const facet*[_M_facets_size];
! _M_names = new char*[_S_categories_size];
}
! catch(...)
{
delete [] _M_facets;
+ delete [] _M_caches;
__throw_exception_again;
}
+
for (size_t __i = 0; __i < _M_facets_size; ++__i)
{
_M_facets[__i] = __imp._M_facets[__i];
+ _M_caches[__i] = __imp._M_caches[__i];
if (_M_facets[__i])
_M_facets[__i]->_M_add_reference();
if (_M_caches[__i])
! _M_caches[__i]->_M_add_reference();
}
! // Name all the categories.
! for (size_t __i = 0; __i < _S_categories_size; ++__i)
! _M_names[__i] = 0;
! try
{
! for (size_t __i = 0; __i < _S_categories_size; ++__i)
! {
! char* __new = new char[std::strlen(__imp._M_names[__i]) + 1];
! std::strcpy(__new, __imp._M_names[__i]);
! _M_names[__i] = __new;
! }
}
catch(...)
{
! this->~_Impl();
__throw_exception_again;
}
}
// Construct named _Impl.
*************** namespace std
*** 172,237 ****
__c_locale __cloc;
locale::facet::_S_create_c_locale(__cloc, __s);
try
- {
- _M_facets = new const facet*[_M_facets_size];
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- _M_facets[__i] = 0;
- }
- catch(...)
- {
- delete [] _M_facets;
- __throw_exception_again;
- }
-
- try
{
! _M_caches = new const facet*[_M_facets_size];
! for (size_t __i = 0; __i < _M_facets_size; ++__i)
! _M_caches[__i] = 0;
}
catch(...)
{
delete [] _M_caches;
__throw_exception_again;
! }
// Name all the categories.
! try
! {
! _M_names = new char*[_S_categories_size];
! }
! catch(...)
! {
! delete [] _M_names;
! __throw_exception_again;
! }
! size_t __len = std::strlen(__s);
! if (!std::strchr(__s, ';'))
{
! for (size_t __i = 0; __i < _S_categories_size; ++__i)
{
! _M_names[__i] = new char[__len + 1];
! std::strcpy(_M_names[__i], __s);
}
! }
! else
! {
! const char* __beg = __s;
! for (size_t __i = 0; __i < _S_categories_size; ++__i)
{
! __beg = std::strchr(__beg, '=') + 1;
! const char* __end = std::strchr(__beg, ';');
! if (!__end)
! __end = __s + __len;
! char* __new = new char[__end - __beg + 1];
! std::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<char>(__cloc, 0, false));
_M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
_M_init_facet(new numpunct<char>(__cloc));
--- 165,225 ----
__c_locale __cloc;
locale::facet::_S_create_c_locale(__cloc, __s);
+ _M_facets = _M_caches = 0;
+ _M_names = 0;
try
{
! _M_facets = new const facet*[_M_facets_size];
! _M_caches = new const facet*[_M_facets_size];
! _M_names = new char*[_S_categories_size];
}
catch(...)
{
+ delete [] _M_facets;
delete [] _M_caches;
__throw_exception_again;
! }
!
! for (size_t __i = 0; __i < _M_facets_size; ++__i)
! _M_facets[__i] = _M_caches[__i] = 0;
// Name all the categories.
! for (size_t __i = 0; __i < _S_categories_size; ++__i)
! _M_names[__i] = 0;
! try
{
! const size_t __len = std::strlen(__s);
! if (!std::strchr(__s, ';'))
{
! for (size_t __i = 0; __i < _S_categories_size; ++__i)
! {
! _M_names[__i] = new char[__len + 1];
! std::strcpy(_M_names[__i], __s);
! }
}
! else
{
! const char* __beg = __s;
! for (size_t __i = 0; __i < _S_categories_size; ++__i)
! {
! __beg = std::strchr(__beg, '=') + 1;
! const char* __end = std::strchr(__beg, ';');
! if (!__end)
! __end = __s + __len;
! char* __new = new char[__end - __beg + 1];
! std::memcpy(__new, __beg, __end - __beg);
! __new[__end - __beg] = '\0';
! _M_names[__i] = __new;
! }
}
}
+ catch(...)
+ {
+ this->~_Impl();
+ __throw_exception_again;
+ }
! // Construct all standard facets and add them to _M_facets.
_M_init_facet(new std::ctype<char>(__cloc, 0, false));
_M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
_M_init_facet(new numpunct<char>(__cloc));
*************** namespace std
*** 263,268 ****
--- 251,257 ----
_M_init_facet(new time_put<wchar_t>);
_M_init_facet(new std::messages<wchar_t>(__cloc, __s));
#endif
+
locale::facet::_S_destroy_c_locale(__cloc);
}
*************** namespace std
*** 277,296 ****
locale::facet::_S_create_c_locale(locale::facet::_S_c_locale,
locale::facet::_S_c_name);
! _M_facets = new (&facet_vec) const facet*[_M_facets_size];
! for (size_t __i = 0; __i < _M_facets_size; ++__i)
! _M_facets[__i] = 0;
!
! _M_caches = new (&cache_vec) const facet*[_M_facets_size];
for (size_t __i = 0; __i < _M_facets_size; ++__i)
! _M_caches[__i] = 0;
// Name all the categories.
- _M_names = new (&name_vec) char*[_S_categories_size];
for (size_t __i = 0; __i < _S_categories_size; ++__i)
{
! _M_names[__i] = new (&name_c[__i]) char[2];
! strcpy(_M_names[__i], locale::facet::_S_c_name);
}
// This is needed as presently the C++ version of "C" locales
--- 266,304 ----
locale::facet::_S_create_c_locale(locale::facet::_S_c_locale,
locale::facet::_S_c_name);
! _M_facets = _M_caches = 0;
! _M_names = 0;
! try
! {
! _M_facets = new (&facet_vec) const facet*[_M_facets_size];
! _M_caches = new (&cache_vec) const facet*[_M_facets_size];
! _M_names = new (&name_vec) char*[_S_categories_size];
! }
! catch(...)
! {
! delete [] _M_facets;
! delete [] _M_caches;
! __throw_exception_again;
! }
!
for (size_t __i = 0; __i < _M_facets_size; ++__i)
! _M_facets[__i] = _M_caches[__i] = 0;
// Name all the categories.
for (size_t __i = 0; __i < _S_categories_size; ++__i)
+ _M_names[__i] = 0;
+ try
+ {
+ for (size_t __i = 0; __i < _S_categories_size; ++__i)
+ {
+ _M_names[__i] = new (&name_c[__i]) char[2];
+ std::strcpy(_M_names[__i], locale::facet::_S_c_name);
+ }
+ }
+ catch(...)
{
! this->~_Impl();
! __throw_exception_again;
}
// This is needed as presently the C++ version of "C" locales
*************** namespace std
*** 357,363 ****
_M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
_M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
#endif
!
// This locale is safe to pre-cache, after all the facets have
// been created and installed.
_M_caches[numpunct<char>::id._M_id()] = __npc;
--- 365,371 ----
_M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
_M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
#endif
!
// This locale is safe to pre-cache, after all the facets have
// been created and installed.
_M_caches[numpunct<char>::id._M_id()] = __npc;
*************** namespace std
*** 388,396 ****
if (std::strcmp(_M_names[__ix], "*") != 0
&& std::strcmp(__imp->_M_names[__ix], "*") != 0)
{
- delete [] _M_names[__ix];
char* __new = new char[std::strlen(__imp->_M_names[__ix]) + 1];
std::strcpy(__new, __imp->_M_names[__ix]);
_M_names[__ix] = __new;
}
}
--- 396,404 ----
if (std::strcmp(_M_names[__ix], "*") != 0
&& std::strcmp(__imp->_M_names[__ix], "*") != 0)
{
char* __new = new char[std::strlen(__imp->_M_names[__ix]) + 1];
std::strcpy(__new, __imp->_M_names[__ix]);
+ delete [] _M_names[__ix];
_M_names[__ix] = __new;
}
}
*************** namespace std
*** 440,446 ****
// New cache array.
const facet** __oldc = _M_caches;
const facet** __newc;
! __newc = new const facet*[__new_size];
for (size_t __i = 0; __i < _M_facets_size; ++__i)
__newc[__i] = _M_caches[__i];
for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
--- 448,462 ----
// New cache array.
const facet** __oldc = _M_caches;
const facet** __newc;
! try
! {
! __newc = new const facet*[__new_size];
! }
! catch(...)
! {
! delete [] __newf;
! __throw_exception_again;
! }
for (size_t __i = 0; __i < _M_facets_size; ++__i)
__newc[__i] = _M_caches[__i];
for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
diff -prN libstdc++-v3-orig/testsuite/22_locale/locale/cons/12352.cc libstdc++-v3/testsuite/22_locale/locale/cons/12352.cc
*** libstdc++-v3-orig/testsuite/22_locale/locale/cons/12352.cc Thu Jan 1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/locale/cons/12352.cc Thu Sep 25 13:54:55 2003
***************
*** 0 ****
--- 1,124 ----
+ // Copyright (C) 2003 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 2, 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 COPYING. If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+
+ // 22.1.1.2 locale constructors and destructors [lib.locale.cons]
+
+ #include <new>
+ #include <locale>
+ #include <cstdlib>
+ #include <cstring>
+
+ int times_to_fail = 0;
+
+ void* allocate(std::size_t n)
+ {
+ if (!times_to_fail--)
+ return 0;
+
+ void* ret = std::malloc(n ? n : 1);
+ if (ret)
+ std::memset(ret, 0xbc, n);
+ return ret;
+ }
+
+ void deallocate(void* p)
+ {
+ if (p)
+ std::free(p);
+ }
+
+ void* operator new(std::size_t n) throw (std::bad_alloc)
+ {
+ void* ret = allocate(n);
+ if (!ret)
+ throw std::bad_alloc();
+ return ret;
+ }
+
+ void* operator new[](std::size_t n) throw (std::bad_alloc)
+ {
+ void* ret = allocate(n);
+ if (!ret)
+ throw std::bad_alloc();
+ return ret;
+ }
+
+ void operator delete(void* p) throw()
+ {
+ deallocate(p);
+ }
+
+ void operator delete[](void* p) throw()
+ {
+ deallocate(p);
+ }
+
+ void* operator new(std::size_t n, const std::nothrow_t&) throw()
+ {
+ return allocate(n);
+ }
+
+ void* operator new[](std::size_t n, const std::nothrow_t&) throw()
+ {
+ return allocate(n);
+ }
+
+ void operator delete(void* p, const std::nothrow_t&) throw()
+ {
+ deallocate(p);
+ }
+
+ void operator delete[](void* p, const std::nothrow_t&) throw()
+ {
+ deallocate(p);
+ }
+
+ // libstdc++/12352
+ void test01(int iters)
+ {
+ using namespace std;
+ bool test = true;
+
+ for (int j = 0; j < iters; ++j)
+ {
+ for (int i = 0; i < 100; ++i)
+ {
+ times_to_fail = i;
+ try
+ {
+ locale loc1("");
+ locale loc2(loc1, locale::classic(), locale::numeric);
+ }
+ catch (exception&)
+ {
+ }
+ }
+ }
+ }
+
+ int main(int argc, char* argv[])
+ {
+ int iters = 1;
+ if (argc > 1)
+ iters = std::atoi(argv[1]);
+ if (iters < 1)
+ iters = 1;
+ test01(iters);
+
+ return 0;
+ }