re PR libstdc++/12352 (Exception safety problems in src/localename.cc)

2003-09-25  Paolo Carlini  <pcarlini@unitus.it>

	PR libstdc++/12352
	* src/localename.cc (locale::_Impl::_Impl(const _Impl&,
	size_t)): Don't leak if memory allocations for _M_facets,
	_M_caches, and _M_names fail.
	(locale::_Impl::_Impl(const char*, size_t)): 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.

	* src/localename.cc (locale::_Impl::_Impl(facet**, size_t,
	bool)): Qualify with std:: strcpy, tweak.
	* include/bits/locale_classes.h
	(locale::_Impl::_M_check_same_name): Qualify strcmp.

From-SVN: r71808
This commit is contained in:
Paolo Carlini 2003-09-26 02:22:01 +02:00 committed by Paolo Carlini
parent 81a1dd1872
commit 91675f9d25
4 changed files with 244 additions and 89 deletions

View File

@ -1,3 +1,23 @@
2003-09-25 Paolo Carlini <pcarlini@unitus.it>
PR libstdc++/12352
* src/localename.cc (locale::_Impl::_Impl(const _Impl&,
size_t)): Don't leak if memory allocations for _M_facets,
_M_caches, and _M_names fail.
(locale::_Impl::_Impl(const char*, size_t)): 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.
* src/localename.cc (locale::_Impl::_Impl(facet**, size_t,
bool)): Qualify with std:: strcpy, tweak.
* include/bits/locale_classes.h
(locale::_Impl::_M_check_same_name): Qualify strcmp.
2003-09-25 Brad Spencer <spencer@infointeractive.com>
PR libstdc++/6072

View File

@ -346,7 +346,7 @@ namespace std
{
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);
__ret &= (std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
return __ret;
}
@ -379,13 +379,30 @@ 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; ++__i)
char* _M_tmp_names[_S_categories_size];
size_t __i = 0;
try
{
delete [] _M_impl->_M_names[__i];
char* __new = new char[2];
std::strcpy(__new, "*");
_M_impl->_M_names[__i] = __new;
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

View File

@ -44,7 +44,7 @@ namespace __gnu_cxx
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 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;
@ -111,55 +111,48 @@ namespace std
_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];
for (size_t __i = 0; __i < _M_facets_size; ++__i)
_M_facets[__i] = 0;
_M_caches = new const facet*[_M_facets_size];
_M_names = new char*[_S_categories_size];
}
catch(...)
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();
}
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();
_M_caches[__i]->_M_add_reference();
}
try
// Name all the categories.
for (size_t __i = 0; __i < _S_categories_size; ++__i)
_M_names[__i] = 0;
try
{
_M_names = new char*[_S_categories_size];
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(...)
{
delete [] _M_names;
this->~_Impl();
__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.
@ -172,66 +165,61 @@ namespace std
__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];
for (size_t __i = 0; __i < _M_facets_size; ++__i)
_M_facets[__i] = 0;
{
_M_facets = new const facet*[_M_facets_size];
_M_caches = new const facet*[_M_facets_size];
_M_names = new char*[_S_categories_size];
}
catch(...)
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;
}
}
for (size_t __i = 0; __i < _M_facets_size; ++__i)
_M_facets[__i] = _M_caches[__i] = 0;
// Name all the categories.
try
for (size_t __i = 0; __i < _S_categories_size; ++__i)
_M_names[__i] = 0;
try
{
_M_names = new char*[_S_categories_size];
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(...)
{
delete [] _M_names;
this->~_Impl();
__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.
// 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));
@ -263,6 +251,7 @@ namespace std
_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);
}
@ -278,19 +267,16 @@ namespace std
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;
_M_facets[__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);
std::strcpy(_M_names[__i], locale::facet::_S_c_name);
}
// This is needed as presently the C++ version of "C" locales
@ -357,7 +343,7 @@ namespace std
_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;
@ -388,9 +374,9 @@ namespace std
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]);
delete [] _M_names[__ix];
_M_names[__ix] = __new;
}
}
@ -440,7 +426,15 @@ namespace std
// New cache array.
const facet** __oldc = _M_caches;
const facet** __newc;
__newc = new const facet*[__new_size];
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)

View File

@ -0,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;
}