[Python-checkins] r67623 - in python/branches/release30-maint: Lib/test/test_bytes.py Misc/NEWS Objects/bytearrayobject.c
antoine.pitrou
python-checkins at python.org
Sun Dec 7 01:07:58 CET 2008
Author: antoine.pitrou
Date: Sun Dec 7 01:07:58 2008
New Revision: 67623
Log:
Merged revisions 67618 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r67618 | antoine.pitrou | 2008-12-06 22:27:53 +0100 (sam., 06 déc. 2008) | 1 line
Issue #4509: bugs in bytearray with exports (buffer protocol)
........
Modified:
python/branches/release30-maint/ (props changed)
python/branches/release30-maint/Lib/test/test_bytes.py
python/branches/release30-maint/Misc/NEWS
python/branches/release30-maint/Objects/bytearrayobject.c
Modified: python/branches/release30-maint/Lib/test/test_bytes.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_bytes.py (original)
+++ python/branches/release30-maint/Lib/test/test_bytes.py Sun Dec 7 01:07:58 2008
@@ -769,6 +769,37 @@
self.assertEqual(b, b"")
self.assertEqual(c, b"")
+ def test_resize_forbidden(self):
+ # #4509: can't resize a bytearray when there are buffer exports, even
+ # if it wouldn't reallocate the underlying buffer.
+ # Furthermore, no destructive changes to the buffer may be applied
+ # before raising the error.
+ b = bytearray(range(10))
+ v = memoryview(b)
+ def resize(n):
+ b[1:-1] = range(n + 1, 2*n - 1)
+ resize(10)
+ orig = b[:]
+ self.assertRaises(BufferError, resize, 11)
+ self.assertEquals(b, orig)
+ self.assertRaises(BufferError, resize, 9)
+ self.assertEquals(b, orig)
+ self.assertRaises(BufferError, resize, 0)
+ self.assertEquals(b, orig)
+ # Other operations implying resize
+ self.assertRaises(BufferError, b.pop, 0)
+ self.assertEquals(b, orig)
+ self.assertRaises(BufferError, b.remove, b[1])
+ self.assertEquals(b, orig)
+ def delitem():
+ del b[1]
+ self.assertRaises(BufferError, delitem)
+ self.assertEquals(b, orig)
+ # deleting a non-contiguous slice
+ def delslice():
+ b[1:-1:2] = b""
+ self.assertRaises(BufferError, delslice)
+ self.assertEquals(b, orig)
class AssortedBytesTest(unittest.TestCase):
#
Modified: python/branches/release30-maint/Misc/NEWS
==============================================================================
--- python/branches/release30-maint/Misc/NEWS (original)
+++ python/branches/release30-maint/Misc/NEWS Sun Dec 7 01:07:58 2008
@@ -16,6 +16,9 @@
growing read buffer. Fixed by using the same growth rate algorithm as
Python 2.x.
+- Issue #4509: Various issues surrounding resize of bytearray objects to
+ which there are buffer exports (e.g. memoryview instances).
+
Library
-------
Modified: python/branches/release30-maint/Objects/bytearrayobject.c
==============================================================================
--- python/branches/release30-maint/Objects/bytearrayobject.c (original)
+++ python/branches/release30-maint/Objects/bytearrayobject.c Sun Dec 7 01:07:58 2008
@@ -100,6 +100,17 @@
return view->len;
}
+static int
+_canresize(PyByteArrayObject *self)
+{
+ if (self->ob_exports > 0) {
+ PyErr_SetString(PyExc_BufferError,
+ "Existing exports of data: object cannot be re-sized");
+ return 0;
+ }
+ return 1;
+}
+
/* Direct API functions */
PyObject *
@@ -180,6 +191,13 @@
assert(PyByteArray_Check(self));
assert(size >= 0);
+ if (size == Py_SIZE(self)) {
+ return 0;
+ }
+ if (!_canresize((PyByteArrayObject *)self)) {
+ return -1;
+ }
+
if (size < alloc / 2) {
/* Major downsize; resize down to exact size */
alloc = size + 1;
@@ -199,16 +217,6 @@
alloc = size + 1;
}
- if (((PyByteArrayObject *)self)->ob_exports > 0) {
- /*
- fprintf(stderr, "%d: %s", ((PyByteArrayObject *)self)->ob_exports,
- ((PyByteArrayObject *)self)->ob_bytes);
- */
- PyErr_SetString(PyExc_BufferError,
- "Existing exports of data: object cannot be re-sized");
- return -1;
- }
-
sval = PyMem_Realloc(((PyByteArrayObject *)self)->ob_bytes, alloc);
if (sval == NULL) {
PyErr_NoMemory();
@@ -473,6 +481,10 @@
if (avail != needed) {
if (avail > needed) {
+ if (!_canresize(self)) {
+ res = -1;
+ goto finish;
+ }
/*
0 lo hi old_size
| |<----avail----->|<-----tomove------>|
@@ -605,6 +617,8 @@
stop = start;
if (step == 1) {
if (slicelen != needed) {
+ if (!_canresize(self))
+ return -1;
if (slicelen > needed) {
/*
0 start stop old_size
@@ -640,6 +654,8 @@
/* Delete slice */
Py_ssize_t cur, i;
+ if (!_canresize(self))
+ return -1;
if (step < 0) {
stop = start + 1;
start = stop + step * (slicelen - 1) - 1;
@@ -1401,7 +1417,7 @@
}
goto done;
}
-
+
for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(table[i]);
@@ -2659,6 +2675,8 @@
PyErr_SetString(PyExc_IndexError, "pop index out of range");
return NULL;
}
+ if (!_canresize(self))
+ return NULL;
value = self->ob_bytes[where];
memmove(self->ob_bytes + where, self->ob_bytes + where + 1, n - where);
@@ -2689,6 +2707,8 @@
PyErr_SetString(PyExc_ValueError, "value not found in bytes");
return NULL;
}
+ if (!_canresize(self))
+ return NULL;
memmove(self->ob_bytes + where, self->ob_bytes + where + 1, n - where);
if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)
More information about the Python-checkins
mailing list