@@ -281,19 +281,31 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
281281 return -1 ;
282282 }
283283
284- /* Re-align data to the start of the allocation. */
285- if (logical_offset > 0 ) {
286- /* optimization tradeoff: This is faster than a new allocation when
287- the number of bytes being removed in a resize is small; for large
288- size changes it may be better to just make a new bytes object as
289- _PyBytes_Resize will do a malloc + memcpy internally. */
290- memmove (obj -> ob_bytes , obj -> ob_start ,
291- Py_MIN (requested_size , Py_SIZE (self )));
292- obj -> ob_start = obj -> ob_bytes ;
293- }
294-
295- if (_PyBytes_ResizeKeepOnError (& obj -> ob_bytes_object , alloc ) < 0 ) {
296- return -1 ;
284+ if (logical_offset == 0 || requested_size >= Py_SIZE (self )) {
285+ /* Re-align data to the start of the allocation. */
286+ if (logical_offset > 0 ) {
287+ /* optimization tradeoff: This is faster than a new allocation when
288+ the number of bytes being removed in a resize is small; for large
289+ size changes it may be better to just make a new bytes object as
290+ _PyBytes_Resize will do a malloc + memcpy internally. */
291+ memmove (obj -> ob_bytes , obj -> ob_start , Py_SIZE (self ));
292+ obj -> ob_start = obj -> ob_bytes ;
293+ }
294+
295+ if (_PyBytes_ResizeKeepOnError (& obj -> ob_bytes_object , alloc ) < 0 ) {
296+ return -1 ;
297+ }
298+ }
299+ else {
300+ // Using memmove() would be unsafe, since _PyBytes_ResizeKeepOnError()
301+ // failure code path would be unable to restore the bytearray to its
302+ // previous state.
303+ PyObject * resized = PyBytes_FromStringAndSize (NULL , requested_size );
304+ if (resized == NULL ) {
305+ return -1 ;
306+ }
307+ memcpy (PyBytes_AS_STRING (resized ), obj -> ob_start , requested_size );
308+ Py_SETREF (obj -> ob_bytes_object , resized );
297309 }
298310
299311 bytearray_reinit_from_bytes (obj , size , alloc );
0 commit comments