Index: Lib/test/test_locale.py =================================================================== --- Lib/test/test_locale.py (revision 78171) +++ Lib/test/test_locale.py (working copy) @@ -364,6 +364,23 @@ # crasher from bug #7419 self.assertRaises(locale.Error, locale.setlocale, 12345) + def test_set_ctype_before_mbstowcs(self): + # Issue 7442 + lc_ctype = locale.setlocale(locale.LC_CTYPE) + lc_numeric = locale.setlocale(locale.LC_NUMERIC) + lc_monetary = locale.setlocale(locale.LC_MONETARY) + locale.setlocale(locale.LC_CTYPE, 'C') + try: + locale.setlocale(locale.LC_NUMERIC, 'fi_FI') + locale.setlocale(locale.LC_MONETARY, 'fi_FI') + except locale.Error: + pass + try: + locale.localeconv() + finally: + locale.setlocale(locale.LC_CTYPE, lc_ctype) + locale.setlocale(locale.LC_NUMERIC, lc_numeric) + locale.setlocale(locale.LC_MONETARY, lc_monetary) def test_main(): tests = [ Index: Modules/_localemodule.c =================================================================== --- Modules/_localemodule.c (revision 78171) +++ Modules/_localemodule.c (working copy) @@ -164,6 +164,16 @@ return result_object; } +static char * +localedup(int category) +{ + char *locale; + + if ((locale = setlocale(category, NULL)) == NULL) + return NULL; + return strdup(locale); +} + PyDoc_STRVAR(localeconv__doc__, "() -> dict. Returns numeric and monetary locale-specific parameters."); @@ -172,7 +182,11 @@ { PyObject* result; struct lconv *l; - PyObject *x; + PyObject *x = NULL; + char *lc_numeric = NULL; + char *lc_monetary = NULL; + char *lc_ctype = NULL; + int set_ctype = 0; result = PyDict_New(); if (!result) @@ -196,7 +210,17 @@ PyDict_SetItemString(result, #i, x);\ Py_XDECREF(x) + lc_ctype = localedup(LC_CTYPE); + lc_numeric = localedup(LC_NUMERIC); + lc_monetary = localedup(LC_MONETARY); + if (!lc_ctype || !lc_numeric || !lc_monetary) + goto failed; + /* Numeric information */ + if (strcmp(lc_numeric, lc_ctype)) { + set_ctype = 1; + setlocale(LC_CTYPE, lc_numeric); + } RESULT_STRING(decimal_point); RESULT_STRING(thousands_sep); x = copy_grouping(l->grouping); @@ -206,6 +230,10 @@ Py_XDECREF(x); /* Monetary information */ + if (strcmp(lc_monetary, set_ctype?lc_numeric:lc_ctype)) { + set_ctype = 1; + setlocale(LC_CTYPE, lc_monetary); + } RESULT_STRING(int_curr_symbol); RESULT_STRING(currency_symbol); RESULT_STRING(mon_decimal_point); @@ -225,12 +253,22 @@ RESULT_INT(n_sep_by_space); RESULT_INT(p_sign_posn); RESULT_INT(n_sign_posn); + + out: + if (lc_ctype) { + if (set_ctype) + setlocale(LC_CTYPE, lc_ctype); + free(lc_ctype); + } + if (lc_numeric) free(lc_numeric); + if (lc_monetary) free(lc_monetary); return result; failed: Py_XDECREF(result); Py_XDECREF(x); - return NULL; + result = NULL; + goto out; } #if defined(HAVE_WCSCOLL) @@ -549,7 +587,7 @@ PyDoc_STRVAR(textdomain__doc__, "textdomain(domain) -> string\n" -"Set the C library's textdmain to domain, returning the new domain."); +"Set the C library's textdomain to domain, returning the new domain."); static PyObject* PyIntl_textdomain(PyObject* self, PyObject* args)