STINNER Victor added the comment:

This issue is tricky, I will try to explain it.

To understand the bug, I wrote the following function:

static int
_PyByteArray_CheckConsistency(PyByteArrayObject *obj)
{
    assert(obj != NULL);
    assert(PyByteArray_Check(obj));

    assert(Py_SIZE(obj) >= 0);
    assert(obj->ob_bytes <= obj->ob_start);
    assert((obj->ob_start - obj->ob_bytes) <= obj->ob_alloc);
    assert((obj->ob_alloc - (obj->ob_start - obj->ob_bytes)) >= Py_SIZE(obj));
    return 1;
}


In this issue, I'm concerned by bytearray_setslice_linear() with growth < 0. 
There are two cases:

(A) lo == 0
(B) lo != 0.


(A) It's trivial to rollback the change: restore previous value of ob_start. 
(Another option is to update the size, which should be the same if I understood 
correctly.) You retrieve the original object.

Expected result:

>>> b=bytearray(b'1234567890')
>>> del b[:6]
>>> b
bytearray(b'7890')

Current behaviour on MemoryError

>>> b=bytearray(b'1234567890')
>>> del b[:6]
>>> b
bytearray(b'7890\x00\xfb\xfb\xfb\xfb\xfb')

With the patch:

>>> b=bytearray(b'1234567890')
>>> del b[:6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError
>>> b
bytearray(b'1234567890')



(B) You cannot restore removed bytes. Currently, you get an inconsistent 
bytearray object because its content is updated but not its size.

No error:

>>> b=bytearray(b'1234567890')
>>> del b[3:6]
>>> b
bytearray(b'1237890')

Current behaviour on MemoryError:

>>> b=bytearray(b'1234567890')
>>> del b[3:6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError
>>> b
bytearray(b'1237890890')

With the patch:

>>> b=bytearray(b'1234567890')
>>> del b[3:6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError
>>> b
bytearray(b'1237890')

With the patch, the deletion succeeded even if you get a MemoryError. The 
bytearray object is consistent. It's just that its buffer could be smaller (it 
wastes memory).


Note: I used gdb to inject a MemoryError in PyByteArray_Resize().

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue19568>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to