Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (revision 57477) +++ Objects/unicodeobject.c (working copy) @@ -7730,12 +7730,19 @@ */ #define FORMATBUFLEN (size_t)120 +/* Constants for the type of % argument being used -- not known, + a mapping, or a tuple. */ +#define FORMAT_TYPE_UNKNOWN 0 +#define FORMAT_TYPE_MAPPING 1 +#define FORMAT_TYPE_TUPLE 2 + PyObject *PyUnicode_Format(PyObject *format, PyObject *args) { Py_UNICODE *fmt, *res; Py_ssize_t fmtcnt, rescnt, reslen, arglen, argidx; int args_owned = 0; + int format_type = FORMAT_TYPE_UNKNOWN; PyUnicodeObject *result = NULL; PyObject *dict = NULL; PyObject *uformat; @@ -7806,6 +7813,13 @@ "format requires a mapping"); goto onError; } + if (format_type == FORMAT_TYPE_TUPLE) { + PyErr_SetString(PyExc_ValueError, + "both keyed and unkeyed format " + "specifiers used"); + goto onError; + } + format_type = FORMAT_TYPE_MAPPING; ++fmt; --fmtcnt; keystart = fmt; @@ -7849,6 +7863,15 @@ arglen = -1; argidx = -2; } + else if (format_type == FORMAT_TYPE_MAPPING) { + PyErr_SetString(PyExc_ValueError, + "both keyed and unkeyed format specifiers used" + ); + goto onError; + } + else if (format_type == FORMAT_TYPE_UNKNOWN) { + format_type = FORMAT_TYPE_TUPLE; + } while (--fmtcnt >= 0) { switch (c = *fmt++) { case '-': flags |= F_LJUST; continue; Index: Objects/stringobject.c =================================================================== --- Objects/stringobject.c (revision 57477) +++ Objects/stringobject.c (working copy) @@ -4455,6 +4455,12 @@ */ #define FORMATBUFLEN (size_t)120 +/* Constants for the type of % argument being used -- not known, + a mapping, or a tuple. */ +#define FORMAT_TYPE_UNKNOWN 0 +#define FORMAT_TYPE_MAPPING 1 +#define FORMAT_TYPE_TUPLE 2 + PyObject * PyString_Format(PyObject *format, PyObject *args) { @@ -4462,6 +4468,7 @@ Py_ssize_t arglen, argidx; Py_ssize_t reslen, rescnt, fmtcnt; int args_owned = 0; + int format_type = FORMAT_TYPE_UNKNOWN; PyObject *result, *orig_args; #ifdef Py_USING_UNICODE PyObject *v, *w; @@ -4534,6 +4541,12 @@ "format requires a mapping"); goto error; } + if (format_type == FORMAT_TYPE_TUPLE) { + PyErr_SetString(PyExc_ValueError, + "both keyed and unkeyed format specifiers used"); + goto error; + } + format_type = FORMAT_TYPE_MAPPING; ++fmt; --fmtcnt; keystart = fmt; @@ -4568,6 +4581,14 @@ arglen = -1; argidx = -2; } + else if (format_type == FORMAT_TYPE_MAPPING) { + PyErr_SetString(PyExc_ValueError, + "both keyed and unkeyed format specifiers used"); + goto error; + } + else if (format_type == FORMAT_TYPE_UNKNOWN) { + format_type = FORMAT_TYPE_TUPLE; + } while (--fmtcnt >= 0) { switch (c = *fmt++) { case '-': flags |= F_LJUST; continue;