diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-10-21 12:25:53 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-21 12:25:53 (GMT) |
commit | 914f9a078f997e58cfcfabcbb30fafdd1f277bef (patch) | |
tree | a9b35e53a19dadceb5b426cd99be74497d7d1ced /Objects/bytesobject.c | |
parent | a323cdcb33c8c856e5668acfb2c67ab5198672c4 (diff) | |
download | cpython-914f9a078f997e58cfcfabcbb30fafdd1f277bef.zip cpython-914f9a078f997e58cfcfabcbb30fafdd1f277bef.tar.gz cpython-914f9a078f997e58cfcfabcbb30fafdd1f277bef.tar.bz2 |
bpo-34973: Fix crash in bytes constructor. (GH-9841)
Constructing bytes from mutating list could cause a crash.
Diffstat (limited to 'Objects/bytesobject.c')
-rw-r--r-- | Objects/bytesobject.c | 104 |
1 files changed, 69 insertions, 35 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 22d4687..d1057b9 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2639,49 +2639,83 @@ fail: return NULL; } -#define _PyBytes_FROM_LIST_BODY(x, GET_ITEM) \ - do { \ - PyObject *bytes; \ - Py_ssize_t i; \ - Py_ssize_t value; \ - char *str; \ - PyObject *item; \ - \ - bytes = PyBytes_FromStringAndSize(NULL, Py_SIZE(x)); \ - if (bytes == NULL) \ - return NULL; \ - str = ((PyBytesObject *)bytes)->ob_sval; \ - \ - for (i = 0; i < Py_SIZE(x); i++) { \ - item = GET_ITEM((x), i); \ - value = PyNumber_AsSsize_t(item, NULL); \ - if (value == -1 && PyErr_Occurred()) \ - goto error; \ - \ - if (value < 0 || value >= 256) { \ - PyErr_SetString(PyExc_ValueError, \ - "bytes must be in range(0, 256)"); \ - goto error; \ - } \ - *str++ = (char) value; \ - } \ - return bytes; \ - \ - error: \ - Py_DECREF(bytes); \ - return NULL; \ - } while (0) - static PyObject* _PyBytes_FromList(PyObject *x) { - _PyBytes_FROM_LIST_BODY(x, PyList_GET_ITEM); + Py_ssize_t i, size = PyList_GET_SIZE(x); + Py_ssize_t value; + char *str; + PyObject *item; + _PyBytesWriter writer; + + _PyBytesWriter_Init(&writer); + str = _PyBytesWriter_Alloc(&writer, size); + if (str == NULL) + return NULL; + writer.overallocate = 1; + size = writer.allocated; + + for (i = 0; i < PyList_GET_SIZE(x); i++) { + item = PyList_GET_ITEM(x, i); + Py_INCREF(item); + value = PyNumber_AsSsize_t(item, NULL); + Py_DECREF(item); + if (value == -1 && PyErr_Occurred()) + goto error; + + if (value < 0 || value >= 256) { + PyErr_SetString(PyExc_ValueError, + "bytes must be in range(0, 256)"); + goto error; + } + + if (i >= size) { + str = _PyBytesWriter_Resize(&writer, str, size+1); + if (str == NULL) + return NULL; + size = writer.allocated; + } + *str++ = (char) value; + } + return _PyBytesWriter_Finish(&writer, str); + + error: + _PyBytesWriter_Dealloc(&writer); + return NULL; } static PyObject* _PyBytes_FromTuple(PyObject *x) { - _PyBytes_FROM_LIST_BODY(x, PyTuple_GET_ITEM); + PyObject *bytes; + Py_ssize_t i, size = PyTuple_GET_SIZE(x); + Py_ssize_t value; + char *str; + PyObject *item; + + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) + return NULL; + str = ((PyBytesObject *)bytes)->ob_sval; + + for (i = 0; i < size; i++) { + item = PyTuple_GET_ITEM(x, i); + value = PyNumber_AsSsize_t(item, NULL); + if (value == -1 && PyErr_Occurred()) + goto error; + + if (value < 0 || value >= 256) { + PyErr_SetString(PyExc_ValueError, + "bytes must be in range(0, 256)"); + goto error; + } + *str++ = (char) value; + } + return bytes; + + error: + Py_DECREF(bytes); + return NULL; } static PyObject * |