Constructor locale(const char* std_name), when called with name of nonuniform
locale (like "LC_CTYPE=...;LC_COLLATE=...;..."), can create locale with
incorrect content of some its facets: these facets differ from facets of
locale, created via locale(const locale& other, const char* std_name, category)
with subsequent replacing of categories. While this locale has same name as
argument of locale(const char* std_name). 

This behaviour contradicts description of member-function name() (22.1.1.3,
p5):

If *this has a name, then locale(name().c_str()) is equivalent to *this.

Example below demonstrates contradiction of this statement on curr_symbol()
property of moneypunct<wchar_t> facet:

#include <locale>
#include <cassert>

int main()
{
    using namespace std;

    locale loc(locale("C"), "en_GB.utf8", locale::monetary);
    const moneypunct<wchar_t>& mp = 
        use_facet<moneypunct<wchar_t> >(loc);

    locale loc_copy(loc.name().c_str());
    const moneypunct<wchar_t>& mp_copy = 
        use_facet<moneypunct<wchar_t> >(loc_copy);

    assert(mp.curr_symbol() == mp_copy.curr_symbol());

    return 0;
}

It seems, the source of the problem is a method of filling properties of named
locale. E.g., for moneypunct<wchar_t> facet, the method performs the following:
1)sets the current POSIX locale with given name,
2)sets some properties of C++ locale, using __nl_langinfo_l() function call,
3)the rest properties of C++ locale are obtained from char-versions of them
using mbsrtowcs()-like functions.

But mbsrtowcs() use current LC_CTYPE category, which name may differ from the
name of LC_MONETARY category in nonuniform locale. So mbsrtowcs() assumes that
string, passed to it, belongs to one charset(according to LC_TYPE category
name), while it belongs to the another (according to LC_MONETARY category
name).
This fact entails wrong property value, obtained via such call to mbsrtowcs().
Up to garbage, because implementation doesn't verify result of mbsrtowcs(),
which doesn't set terminating '\0' in case of error.

The fact, that the implementation doest't verify result of mbsrtowcs(), also
seems strange - absence of terminating '\0' may lead to SIGFAULT.


-- 
           Summary: locale(const char* std_name) can create invalid facets
                    for nonuniform locale
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: tsyvarev at ispras dot ru


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40184

Reply via email to