@@ -214,6 +214,47 @@ PyByteArray_AsString(PyObject *self)
214214 return PyByteArray_AS_STRING (self );
215215}
216216
217+
218+ static int
219+ bytearray_realign_data_lock_held (PyByteArrayObject * self , Py_ssize_t new_size , Py_ssize_t alloc )
220+ {
221+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (self );
222+ assert (1 <= new_size && new_size <= alloc );
223+
224+ Py_ssize_t size = Py_SIZE (self );
225+ size_t logical_offset = (size_t ) (self -> ob_start - self -> ob_bytes );
226+
227+ if (logical_offset == 0 || new_size >= size ) {
228+ /* Re-align data to the start of the allocation. */
229+ if (logical_offset != 0 ) {
230+ /* optimization tradeoff: This is faster than a new allocation when
231+ the number of bytes being removed in a resize is small; for
232+ large size changes it may be better to just make a new bytes
233+ object as _PyBytes_Resize will do a malloc + memcpy internally.
234+ */
235+ memmove (self -> ob_bytes , self -> ob_start , size );
236+ self -> ob_start = self -> ob_bytes ;
237+ }
238+
239+ if (_PyBytes_ResizeKeepOnError (& self -> ob_bytes_object , alloc ) < 0 ) {
240+ return -1 ;
241+ }
242+ }
243+ else {
244+ // Using memmove() would be unsafe, since _PyBytes_ResizeKeepOnError()
245+ // failure code path would be unable to restore the bytearray to its
246+ // previous state.
247+ PyObject * resized = PyBytes_FromStringAndSize (NULL , alloc );
248+ if (resized == NULL ) {
249+ return -1 ;
250+ }
251+ memcpy (PyBytes_AS_STRING (resized ), self -> ob_start , new_size );
252+ Py_SETREF (self -> ob_bytes_object , resized );
253+ }
254+ return 0 ;
255+ }
256+
257+
217258static int
218259bytearray_resize_lock_held (PyObject * self , Py_ssize_t requested_size )
219260{
@@ -284,31 +325,9 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
284325 return -1 ;
285326 }
286327
287- if (logical_offset == 0 || requested_size >= Py_SIZE (self )) {
288- /* Re-align data to the start of the allocation. */
289- if (logical_offset > 0 ) {
290- /* optimization tradeoff: This is faster than a new allocation when
291- the number of bytes being removed in a resize is small; for large
292- size changes it may be better to just make a new bytes object as
293- _PyBytes_Resize will do a malloc + memcpy internally. */
294- memmove (obj -> ob_bytes , obj -> ob_start , Py_SIZE (self ));
295- obj -> ob_start = obj -> ob_bytes ;
296- }
297-
298- if (_PyBytes_ResizeKeepOnError (& obj -> ob_bytes_object , alloc ) < 0 ) {
299- return -1 ;
300- }
301- }
302- else {
303- // Using memmove() would be unsafe, since _PyBytes_ResizeKeepOnError()
304- // failure code path would be unable to restore the bytearray to its
305- // previous state.
306- PyObject * resized = PyBytes_FromStringAndSize (NULL , alloc );
307- if (resized == NULL ) {
308- return -1 ;
309- }
310- memcpy (PyBytes_AS_STRING (resized ), obj -> ob_start , requested_size );
311- Py_SETREF (obj -> ob_bytes_object , resized );
328+ if (bytearray_realign_data_lock_held (obj , requested_size ,
329+ (Py_ssize_t )alloc ) < 0 ) {
330+ return -1 ;
312331 }
313332
314333 bytearray_reinit_from_bytes (obj , size );
@@ -1646,30 +1665,9 @@ bytearray_take_bytes_impl(PyByteArrayObject *self, PyObject *n)
16461665 memcpy (PyBytes_AS_STRING (remaining ), self -> ob_start + to_take ,
16471666 remaining_length );
16481667
1649- size_t logical_offset = (size_t ) (self -> ob_start - self -> ob_bytes );
1650- if (logical_offset == 0 || remaining_length == 0 ) {
1651- // If the bytes are offset inside the buffer must first align.
1652- if (logical_offset != 0 ) {
1653- memmove (self -> ob_bytes , self -> ob_start , to_take );
1654- self -> ob_start = self -> ob_bytes ;
1655- }
1656-
1657- if (_PyBytes_ResizeKeepOnError (& self -> ob_bytes_object , to_take ) == -1 ) {
1658- Py_DECREF (remaining );
1659- return NULL ;
1660- }
1661- }
1662- else {
1663- // Using memmove() would be unsafe, since _PyBytes_ResizeKeepOnError()
1664- // failure code path would be unable to restore the bytearray to its
1665- // previous state.
1666- PyObject * resized = PyBytes_FromStringAndSize (NULL , to_take );
1667- if (resized == NULL ) {
1668- Py_DECREF (remaining );
1669- return NULL ;
1670- }
1671- memcpy (PyBytes_AS_STRING (resized ), self -> ob_start , to_take );
1672- Py_SETREF (self -> ob_bytes_object , resized );
1668+ if (bytearray_realign_data_lock_held (self , to_take , to_take ) < 0 ) {
1669+ Py_DECREF (remaining );
1670+ return NULL ;
16731671 }
16741672
16751673 // Point the bytearray towards the buffer with the remaining data.
0 commit comments