Index: Include/unicodeobject.h =================================================================== --- Include/unicodeobject.h (révision 84621) +++ Include/unicodeobject.h (copie de travail) @@ -550,8 +550,14 @@ register PyObject *obj /* Object */ ); -PyAPI_FUNC(PyObject *) PyUnicode_FromFormatV(const char*, va_list); -PyAPI_FUNC(PyObject *) PyUnicode_FromFormat(const char*, ...); +PyAPI_FUNC(PyObject *) PyUnicode_FromFormatV( + const char *format, /* ASCII-encoded string */ + va_list vargs + ); +PyAPI_FUNC(PyObject *) PyUnicode_FromFormat( + const char *format, /* ASCII-encoded string */ + ... + ); /* Format the object based on the format_spec, as defined in PEP 3101 (Advanced String Formatting). */ Index: Include/pyerrors.h =================================================================== --- Include/pyerrors.h (révision 84621) +++ Include/pyerrors.h (copie de travail) @@ -183,7 +183,11 @@ PyObject *, const Py_UNICODE *); #endif /* MS_WINDOWS */ -PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...); +PyAPI_FUNC(PyObject *) PyErr_Format( + PyObject *exception, + const char *format, /* ASCII-encoded string */ + ... + ); #ifdef MS_WINDOWS PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenameObject( Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (révision 84621) +++ Objects/unicodeobject.c (copie de travail) @@ -1102,7 +1102,15 @@ appendstring(p); goto end; } - } else + } + else if (128 <= (unsigned char)*f) { + PyErr_Format(PyExc_ValueError, + "PyUnicode_FromFormatV() expects an ASCII-encoded format " + "string, got a non-ascii byte: 0x%02x", + *f); + goto fail; + } + else *s++ = *f; } Index: Lib/test/test_unicode.py =================================================================== --- Lib/test/test_unicode.py (révision 84621) +++ Lib/test/test_unicode.py (copie de travail) @@ -1385,7 +1385,19 @@ self.assertEquals("%s" % s, '__str__ overridden') self.assertEquals("{}".format(s), '__str__ overridden') + def test_from_format(self): + # Ensure that PyUnicode_FromFormat() raises an error for a non-ascii + # format string. + from _testcapi import format_unicode + # ascii format, non-ascii argument + text = format_unicode(b'ascii\x7f=%U', 'unicode\xe9') + self.assertEqual(text, 'ascii\x7f=unicode\xe9') + + # non-ascii format, ascii argument + self.assertRaises(ValueError, + format_unicode, b'unicode\xe9=%s', 'ascii') + def test_main(): support.run_unittest(__name__) Index: Modules/_testcapimodule.c =================================================================== --- Modules/_testcapimodule.c (révision 84621) +++ Modules/_testcapimodule.c (copie de travail) @@ -2193,6 +2193,17 @@ return NULL; } +static PyObject * +format_unicode(PyObject *self, PyObject *args) +{ + const char *format; + PyObject *arg; + if (!PyArg_ParseTuple(args, "yU", &format, &arg)) + return NULL; + return PyUnicode_FromFormat(format, arg); + +} + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS}, @@ -2272,6 +2283,7 @@ {"make_exception_with_doc", (PyCFunction)make_exception_with_doc, METH_VARARGS | METH_KEYWORDS}, {"crash_no_current_thread", (PyCFunction)crash_no_current_thread, METH_NOARGS}, + {"format_unicode", format_unicode, METH_VARARGS}, {NULL, NULL} /* sentinel */ };