b = self.type2test([1, 2, 3])
self.assertEqual(b, b"\x01\x02\x03")
+ def test_from_mutating_list(self):
+ # Issue #34973: Crash in bytes constructor with mutating list.
+ class X:
+ def __index__(self):
+ a.clear()
+ return 42
+ a = [X(), X()]
+ self.assertEqual(bytes(a), b'*')
+
+ class Y:
+ def __index__(self):
+ if len(a) < 1000:
+ a.append(self)
+ return 42
+ a = [Y()]
+ self.assertEqual(bytes(a), b'*' * 1000) # should not crash
+
def test_from_index(self):
b = self.type2test([Indexable(), Indexable(1), Indexable(254),
Indexable(255)])
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 *