diff -r c0e63937efa7 Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c Wed Nov 20 00:14:49 2013 +0100 +++ b/Objects/bytearrayobject.c Wed Nov 20 00:47:39 2013 +0100 @@ -453,6 +453,7 @@ bytearray_setslice_linear(PyByteArrayObj Py_ssize_t avail = hi - lo; char *buf = PyByteArray_AS_STRING(self); Py_ssize_t growth = bytes_len - avail; + int res = 0; assert(avail >= 0); if (growth != 0) { @@ -482,8 +483,28 @@ bytearray_setslice_linear(PyByteArrayObj } /* XXX(nnorwitz): need to verify this can't overflow! */ if (PyByteArray_Resize( - (PyObject *)self, Py_SIZE(self) + growth) < 0) - return -1; + (PyObject *)self, Py_SIZE(self) + growth) < 0) { + /* Issue #19578: Handling the memory allocation failure here is + tricky here because the bytearray object has already been + modified. Depending on growth and lo, the behaviour is + different. + + If growth < 0 and lo != 0, the operation is completed, but a + MemoryError is still raised and the memory block is not + shrinked. Otherwise, the bytearray is restored in its previous + state and a MemoryError is raised. */ + if (growth < 0 && lo != 0) { + /* memmove() removed bytes, the bytearray object cannot be + restored in its previous state. */ + Py_SIZE(self) += growth; + res = -1; + } + else { + if (growth < 0) + self->ob_start += growth; + return -1; + } + } buf = PyByteArray_AS_STRING(self); if (growth > 0) { /* Make the place for the additional bytes */ @@ -500,7 +521,7 @@ bytearray_setslice_linear(PyByteArrayObj if (bytes_len > 0) memcpy(buf + lo, bytes, bytes_len); - return 0; + return res; } static int