diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2015-03-30 06:19:08 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2015-03-30 06:19:08 (GMT) |
commit | 2c7b5a9d0d6587a38f24da1f96f581bad0d3ded6 (patch) | |
tree | 2ead5ca3ad9744179f0a0f6f469ccd69bcd9dae0 /Objects | |
parent | 7901b48a1f89b9bfa9d111ae3725400b466a9baa (diff) | |
download | cpython-2c7b5a9d0d6587a38f24da1f96f581bad0d3ded6.zip cpython-2c7b5a9d0d6587a38f24da1f96f581bad0d3ded6.tar.gz cpython-2c7b5a9d0d6587a38f24da1f96f581bad0d3ded6.tar.bz2 |
Issue #23466: %c, %o, %x, and %X in bytes formatting now raise TypeError on
non-integer input.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/bytesobject.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 4d6b3e4..5a2d41c 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -433,7 +433,41 @@ formatfloat(PyObject *v, int flags, int prec, int type) return result; } -Py_LOCAL_INLINE(int) +static PyObject * +formatlong(PyObject *v, int flags, int prec, int type) +{ + PyObject *result, *iobj; + if (type == 'i') + type = 'd'; + if (PyLong_Check(v)) + return _PyUnicode_FormatLong(v, flags & F_ALT, prec, type); + if (PyNumber_Check(v)) { + /* make sure number is a type of integer for o, x, and X */ + if (type == 'o' || type == 'x' || type == 'X') + iobj = PyNumber_Index(v); + else + iobj = PyNumber_Long(v); + if (iobj == NULL) { + if (!PyErr_ExceptionMatches(PyExc_TypeError)) + return NULL; + } + else if (!PyLong_Check(iobj)) + Py_CLEAR(iobj); + if (iobj != NULL) { + result = _PyUnicode_FormatLong(iobj, flags & F_ALT, prec, type); + Py_DECREF(iobj); + return result; + } + } + PyErr_Format(PyExc_TypeError, + "%%%c format: %s is required, not %.200s", type, + (type == 'o' || type == 'x' || type == 'X') ? "an integer" + : "a number", + Py_TYPE(v)->tp_name); + return NULL; +} + +static int byte_converter(PyObject *arg, char *p) { if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) { @@ -445,12 +479,29 @@ byte_converter(PyObject *arg, char *p) return 1; } else { - long ival = PyLong_AsLong(arg); - if (0 <= ival && ival <= 255) { + PyObject *iobj; + long ival; + int overflow; + /* make sure number is a type of integer */ + if (PyLong_Check(arg)) { + ival = PyLong_AsLongAndOverflow(arg, &overflow); + } + else { + iobj = PyNumber_Index(arg); + if (iobj == NULL) { + if (!PyErr_ExceptionMatches(PyExc_TypeError)) + return 0; + goto onError; + } + ival = PyLong_AsLongAndOverflow(iobj, &overflow); + Py_DECREF(iobj); + } + if (!overflow && 0 <= ival && ival <= 255) { *p = (char)ival; return 1; } } + onError: PyErr_SetString(PyExc_TypeError, "%c requires an integer in range(256) or a single byte"); return 0; @@ -561,7 +612,6 @@ _PyBytes_Format(PyObject *format, PyObject *args) int prec = -1; int c = '\0'; int fill; - PyObject *iobj; PyObject *v = NULL; PyObject *temp = NULL; const char *pbuf = NULL; @@ -747,28 +797,7 @@ _PyBytes_Format(PyObject *format, PyObject *args) case 'o': case 'x': case 'X': - if (c == 'i') - c = 'd'; - iobj = NULL; - if (PyNumber_Check(v)) { - if ((PyLong_Check(v))) { - iobj = v; - Py_INCREF(iobj); - } - else { - iobj = PyNumber_Long(v); - if (iobj != NULL && !PyLong_Check(iobj)) - Py_CLEAR(iobj); - } - } - if (iobj == NULL) { - PyErr_Format(PyExc_TypeError, - "%%%c format: a number is required, " - "not %.200s", c, Py_TYPE(v)->tp_name); - goto error; - } - temp = _PyUnicode_FormatLong(iobj, flags & F_ALT, prec, c); - Py_DECREF(iobj); + temp = formatlong(v, flags, prec, c); if (!temp) goto error; assert(PyUnicode_IS_ASCII(temp)); |