Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8455723

Browse files
committed
Close #19568: Fix bytearray_setslice_linear(), fix handling of
PyByteArray_Resize() failure: leave the bytearray object in an consistent state. If growth < 0, handling the memory allocation failure is tricky here because the bytearray object has already been modified. If lo != 0, the operation is completed, but a MemoryError is still raised and the memory block is not shrinked. If lo == 0, the bytearray is restored in its previous state and a MemoryError is raised.
1 parent 35f2803 commit 8455723

1 file changed

Lines changed: 63 additions & 37 deletions

File tree

Objects/bytearrayobject.c

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -453,54 +453,80 @@ bytearray_setslice_linear(PyByteArrayObject *self,
453453
Py_ssize_t avail = hi - lo;
454454
char *buf = PyByteArray_AS_STRING(self);
455455
Py_ssize_t growth = bytes_len - avail;
456+
int res = 0;
456457
assert(avail >= 0);
457458

458-
if (growth != 0) {
459-
if (growth < 0) {
460-
if (!_canresize(self))
461-
return -1;
459+
if (growth < 0) {
460+
if (!_canresize(self))
461+
return -1;
462+
463+
if (lo == 0) {
464+
/* Shrink the buffer by advancing its logical start */
465+
self->ob_start -= growth;
466+
/*
467+
0 lo hi old_size
468+
| |<----avail----->|<-----tail------>|
469+
| |<-bytes_len->|<-----tail------>|
470+
0 new_lo new_hi new_size
471+
*/
472+
}
473+
else {
474+
/*
475+
0 lo hi old_size
476+
| |<----avail----->|<-----tomove------>|
477+
| |<-bytes_len->|<-----tomove------>|
478+
0 lo new_hi new_size
479+
*/
480+
memmove(buf + lo + bytes_len, buf + hi,
481+
Py_SIZE(self) - hi);
482+
}
483+
if (PyByteArray_Resize((PyObject *)self,
484+
Py_SIZE(self) + growth) < 0) {
485+
/* Issue #19578: Handling the memory allocation failure here is
486+
tricky here because the bytearray object has already been
487+
modified. Depending on growth and lo, the behaviour is
488+
different.
489+
490+
If growth < 0 and lo != 0, the operation is completed, but a
491+
MemoryError is still raised and the memory block is not
492+
shrinked. Otherwise, the bytearray is restored in its previous
493+
state and a MemoryError is raised. */
462494
if (lo == 0) {
463-
/* Shrink the buffer by advancing its logical start */
464-
self->ob_start -= growth;
465-
/*
466-
0 lo hi old_size
467-
| |<----avail----->|<-----tail------>|
468-
| |<-bytes_len->|<-----tail------>|
469-
0 new_lo new_hi new_size
470-
*/
471-
}
472-
else {
473-
/*
474-
0 lo hi old_size
475-
| |<----avail----->|<-----tomove------>|
476-
| |<-bytes_len->|<-----tomove------>|
477-
0 lo new_hi new_size
478-
*/
479-
memmove(buf + lo + bytes_len, buf + hi,
480-
Py_SIZE(self) - hi);
495+
self->ob_start += growth;
496+
return -1;
481497
}
498+
/* memmove() removed bytes, the bytearray object cannot be
499+
restored in its previous state. */
500+
Py_SIZE(self) += growth;
501+
res = -1;
482502
}
483-
/* XXX(nnorwitz): need to verify this can't overflow! */
484-
if (PyByteArray_Resize(
485-
(PyObject *)self, Py_SIZE(self) + growth) < 0)
486-
return -1;
487503
buf = PyByteArray_AS_STRING(self);
488-
if (growth > 0) {
489-
/* Make the place for the additional bytes */
490-
/*
491-
0 lo hi old_size
492-
| |<-avail->|<-----tomove------>|
493-
| |<---bytes_len-->|<-----tomove------>|
494-
0 lo new_hi new_size
495-
*/
496-
memmove(buf + lo + bytes_len, buf + hi,
497-
Py_SIZE(self) - lo - bytes_len);
504+
}
505+
else if (growth > 0) {
506+
if (Py_SIZE(self) > (Py_ssize_t)PY_SSIZE_T_MAX - growth) {
507+
PyErr_NoMemory();
508+
return -1;
498509
}
510+
511+
if (PyByteArray_Resize((PyObject *)self,
512+
Py_SIZE(self) + growth) < 0) {
513+
return -1;
514+
}
515+
buf = PyByteArray_AS_STRING(self);
516+
/* Make the place for the additional bytes */
517+
/*
518+
0 lo hi old_size
519+
| |<-avail->|<-----tomove------>|
520+
| |<---bytes_len-->|<-----tomove------>|
521+
0 lo new_hi new_size
522+
*/
523+
memmove(buf + lo + bytes_len, buf + hi,
524+
Py_SIZE(self) - lo - bytes_len);
499525
}
500526

501527
if (bytes_len > 0)
502528
memcpy(buf + lo, bytes, bytes_len);
503-
return 0;
529+
return res;
504530
}
505531

506532
static int

0 commit comments

Comments
 (0)