summaryrefslogtreecommitdiffstats
path: root/Objects/bytesobject.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-10-21 12:25:53 (GMT)
committerGitHub <noreply@github.com>2018-10-21 12:25:53 (GMT)
commit914f9a078f997e58cfcfabcbb30fafdd1f277bef (patch)
treea9b35e53a19dadceb5b426cd99be74497d7d1ced /Objects/bytesobject.c
parenta323cdcb33c8c856e5668acfb2c67ab5198672c4 (diff)
downloadcpython-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.c104
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 *