This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]