mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-30 07:14:09 +08:00
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:
parent
81a1dd1872
commit
91675f9d25
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
124
libstdc++-v3/testsuite/22_locale/locale/cons/12352.cc
Normal file
124
libstdc++-v3/testsuite/22_locale/locale/cons/12352.cc
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user