diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2009-05-19 18:20:47 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2009-05-19 18:20:47 +0000 |
commit | c8036448d18101ce03661a2e6179d07b6178b6fb (patch) | |
tree | e37754ec220e5fcdd3f4dc0df8225e328e423de0 /libstdc++-v3/src | |
parent | f3a83111278d2fe8a60e8fec8b1fbbeee69d6d31 (diff) | |
download | gcc-c8036448d18101ce03661a2e6179d07b6178b6fb.zip gcc-c8036448d18101ce03661a2e6179d07b6178b6fb.tar.gz gcc-c8036448d18101ce03661a2e6179d07b6178b6fb.tar.bz2 |
re PR libstdc++/40184 (locale(const char* std_name) can create invalid facets for nonuniform locale)
2009-05-19 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/40184
* include/bits/locale_classes.h (locale::facet::_S_lc_ctype_c_locale):
Declare...
* config/locale/gnu/c_locale.cc: ... and define.
* config/locale/generic/c_locale.cc: Define.
* src/localename.cc (locale::_Impl::_Impl(const char*, size_t)):
Use it.
* testsuite/22_locale/locale/cons/40184.cc: New.
From-SVN: r147714
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r-- | libstdc++-v3/src/localename.cc | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc index ae932a3..98f6020 100644 --- a/libstdc++-v3/src/localename.cc +++ b/libstdc++-v3/src/localename.cc @@ -180,6 +180,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // see if the given name is valid. __c_locale __cloc; locale::facet::_S_create_c_locale(__cloc, __s); + __c_locale __clocm = __cloc; __try { @@ -194,15 +195,19 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_names[__k] = 0; // Name the categories. + const char* __smon = __s; const size_t __len = std::strlen(__s); if (!std::memchr(__s, ';', __len)) { _M_names[0] = new char[__len + 1]; - std::memcpy(_M_names[0], __s, __len + 1); + std::memcpy(_M_names[0], __s, __len + 1); } else { const char* __end = __s; + bool __found_ctype = false; + bool __found_monetary = false; + size_t __ci = 0, __mi = 0; for (size_t __i = 0; __i < _S_categories_size; ++__i) { const char* __beg = std::strchr(__end + 1, '=') + 1; @@ -212,6 +217,24 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_names[__i] = new char[__end - __beg + 1]; std::memcpy(_M_names[__i], __beg, __end - __beg); _M_names[__i][__end - __beg] = '\0'; + if (!__found_ctype + && *(__beg - 2) == 'E' && *(__beg - 3) == 'P') + { + __found_ctype = true; + __ci = __i; + } + else if (!__found_monetary && *(__beg - 2) == 'Y') + { + __found_monetary = true; + __mi = __i; + } + } + + if (std::strcmp(_M_names[__ci], _M_names[__mi])) + { + __smon = _M_names[__mi]; + __clocm = locale::facet::_S_lc_ctype_c_locale(__cloc, + __smon); } } @@ -222,8 +245,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_init_facet(new num_get<char>); _M_init_facet(new num_put<char>); _M_init_facet(new std::collate<char>(__cloc)); - _M_init_facet(new moneypunct<char, false>(__cloc, __s)); - _M_init_facet(new moneypunct<char, true>(__cloc, __s)); + _M_init_facet(new moneypunct<char, false>(__cloc, 0)); + _M_init_facet(new moneypunct<char, true>(__cloc, 0)); _M_init_facet(new money_get<char>); _M_init_facet(new money_put<char>); _M_init_facet(new __timepunct<char>(__cloc, __s)); @@ -238,8 +261,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_init_facet(new num_get<wchar_t>); _M_init_facet(new num_put<wchar_t>); _M_init_facet(new std::collate<wchar_t>(__cloc)); - _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s)); - _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s)); + _M_init_facet(new moneypunct<wchar_t, false>(__clocm, __smon)); + _M_init_facet(new moneypunct<wchar_t, true>(__clocm, __smon)); _M_init_facet(new money_get<wchar_t>); _M_init_facet(new money_put<wchar_t>); _M_init_facet(new __timepunct<wchar_t>(__cloc, __s)); @@ -248,10 +271,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_init_facet(new std::messages<wchar_t>(__cloc, __s)); #endif locale::facet::_S_destroy_c_locale(__cloc); + if (__clocm != __cloc) + locale::facet::_S_destroy_c_locale(__clocm); } __catch(...) { locale::facet::_S_destroy_c_locale(__cloc); + if (__clocm != __cloc) + locale::facet::_S_destroy_c_locale(__clocm); this->~_Impl(); __throw_exception_again; } |