summaryrefslogtreecommitdiff
path: root/Objects
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2018-10-21 05:55:52 -0700
committerGitHub <noreply@github.com>2018-10-21 05:55:52 -0700
commit7f34d550231e047c88a1817b58bda03a33817490 (patch)
tree0b1f4145067a2fa34303a0ba29a17a8d4d2fbd66 /Objects
parent002aef3f66a9f8da635e20860622f2e539a0b611 (diff)
downloadcpython-git-7f34d550231e047c88a1817b58bda03a33817490.tar.gz
bpo-34973: Fix crash in bytes constructor. (GH-9841)
Constructing bytes from mutating list could cause a crash. (cherry picked from commit 914f9a078f997e58cfcfabcbb30fafdd1f277bef) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Diffstat (limited to 'Objects')
-rw-r--r--Objects/bytesobject.c104
1 files changed, 69 insertions, 35 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 5b62842093..711faba645 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2640,49 +2640,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 *