Skip to content

Commit 697d3b1

Browse files
committed
Adding write barriers for array
Signed-off-by: Matthew A Johnson <matjoh@microsoft.com>
1 parent 80b648c commit 697d3b1

2 files changed

Lines changed: 113 additions & 0 deletions

File tree

Lib/test/test_freeze.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,60 @@ def test_clear(self):
189189
self.obj.clear()
190190

191191

192+
class TestArray(BaseObjectTest):
193+
def __init__(self, *args, **kwargs):
194+
obj = array('i', [1, 2, 3, 4])
195+
BaseObjectTest.__init__(self, *args, obj=obj, **kwargs)
196+
197+
def test_set_item(self):
198+
with self.assertRaises(NotWriteableError):
199+
self.obj[0] = 5
200+
201+
def test_set_slice(self):
202+
with self.assertRaises(NotWriteableError):
203+
self.obj[1:3] = [6, 7]
204+
205+
def test_append(self):
206+
with self.assertRaises(NotWriteableError):
207+
self.obj.append(8)
208+
209+
def test_extend(self):
210+
with self.assertRaises(NotWriteableError):
211+
self.obj.extend(array('i', [9]))
212+
213+
def test_insert(self):
214+
with self.assertRaises(NotWriteableError):
215+
self.obj.insert(0, 10)
216+
217+
def test_pop(self):
218+
with self.assertRaises(NotWriteableError):
219+
self.obj.pop()
220+
221+
def test_remove(self):
222+
with self.assertRaises(NotWriteableError):
223+
self.obj.remove(1)
224+
225+
def test_delete(self):
226+
with self.assertRaises(NotWriteableError):
227+
del self.obj[0]
228+
229+
def test_reverse(self):
230+
with self.assertRaises(NotWriteableError):
231+
self.obj.reverse()
232+
233+
def test_inplace_repeat(self):
234+
with self.assertRaises(NotWriteableError):
235+
self.obj *= 2
236+
237+
def test_inplace_concat(self):
238+
with self.assertRaises(NotWriteableError):
239+
self.obj += array('i', [11])
240+
241+
def test_byteswap(self):
242+
with self.assertRaises(NotWriteableError):
243+
self.obj.byteswap()
244+
245+
192246
class TestDict(BaseObjectTest):
193247
class C:
194248
pass

Modules/arraymodule.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "Python.h"
1212
#include "pycore_moduleobject.h" // _PyModule_GetState()
1313
#include "pycore_bytesobject.h" // _PyBytes_Repeat
14+
#include "pycore_object.h" // Py_CHECKWRITE
1415
#include "structmember.h" // PyMemberDef
1516
#include <stddef.h> // offsetof()
1617

@@ -1048,6 +1049,10 @@ array_inplace_concat(arrayobject *self, PyObject *bb)
10481049
{
10491050
array_state *state = find_array_state_by_type(Py_TYPE(self));
10501051

1052+
if(!Py_CHECKWRITE(self)){
1053+
return PyErr_WriteToImmutable(self);
1054+
}
1055+
10511056
if (!array_Check(bb, state)) {
10521057
PyErr_Format(PyExc_TypeError,
10531058
"can only extend array with array (not \"%.200s\")",
@@ -1064,6 +1069,10 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
10641069
{
10651070
const Py_ssize_t array_size = Py_SIZE(self);
10661071

1072+
if(!Py_CHECKWRITE(self)){
1073+
return PyErr_WriteToImmutable(self);
1074+
}
1075+
10671076
if (array_size > 0 && n != 1 ) {
10681077
if (n < 0)
10691078
n = 0;
@@ -1087,6 +1096,10 @@ array_inplace_repeat(arrayobject *self, Py_ssize_t n)
10871096
static PyObject *
10881097
ins(arrayobject *self, Py_ssize_t where, PyObject *v)
10891098
{
1099+
if(!Py_CHECKWRITE(self)){
1100+
return PyErr_WriteToImmutable(self);
1101+
}
1102+
10901103
if (ins1(self, where, v) != 0)
10911104
return NULL;
10921105
Py_RETURN_NONE;
@@ -1205,6 +1218,10 @@ array_array_remove(arrayobject *self, PyObject *v)
12051218
{
12061219
Py_ssize_t i;
12071220

1221+
if(!Py_CHECKWRITE(self)){
1222+
return PyErr_WriteToImmutable(self);
1223+
}
1224+
12081225
for (i = 0; i < Py_SIZE(self); i++) {
12091226
PyObject *selfi;
12101227
int cmp;
@@ -1243,6 +1260,10 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i)
12431260
{
12441261
PyObject *v;
12451262

1263+
if(!Py_CHECKWRITE(self)){
1264+
return PyErr_WriteToImmutable(self);
1265+
}
1266+
12461267
if (Py_SIZE(self) == 0) {
12471268
/* Special-case most common failure cause */
12481269
PyErr_SetString(PyExc_IndexError, "pop from empty array");
@@ -1278,6 +1299,10 @@ static PyObject *
12781299
array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb)
12791300
/*[clinic end generated code: output=e65eb7588f0bc266 input=8eb6817ec4d2cb62]*/
12801301
{
1302+
if(!Py_CHECKWRITE(self)){
1303+
return PyErr_WriteToImmutable(self);
1304+
}
1305+
12811306
array_state *state = get_array_state_by_class(cls);
12821307

12831308
if (array_do_extend(state, self, bb) == -1)
@@ -1351,6 +1376,10 @@ static PyObject *
13511376
array_array_append(arrayobject *self, PyObject *v)
13521377
/*[clinic end generated code: output=745a0669bf8db0e2 input=0b98d9d78e78f0fa]*/
13531378
{
1379+
if(!Py_CHECKWRITE(self)){
1380+
return PyErr_WriteToImmutable(self);
1381+
}
1382+
13541383
return ins(self, Py_SIZE(self), v);
13551384
}
13561385

@@ -1370,6 +1399,10 @@ array_array_byteswap_impl(arrayobject *self)
13701399
char *p;
13711400
Py_ssize_t i;
13721401

1402+
if(!Py_CHECKWRITE(self)){
1403+
return PyErr_WriteToImmutable(self);
1404+
}
1405+
13731406
switch (self->ob_descr->itemsize) {
13741407
case 1:
13751408
break;
@@ -1430,6 +1463,10 @@ array_array_reverse_impl(arrayobject *self)
14301463
char tmp[256]; /* 8 is probably enough -- but why skimp */
14311464
assert((size_t)itemsize <= sizeof(tmp));
14321465

1466+
if(!Py_CHECKWRITE(self)){
1467+
return PyErr_WriteToImmutable(self);
1468+
}
1469+
14331470
if (Py_SIZE(self) > 1) {
14341471
for (p = self->ob_item,
14351472
q = self->ob_item + (Py_SIZE(self) - 1)*itemsize;
@@ -1468,6 +1505,10 @@ array_array_fromfile_impl(arrayobject *self, PyTypeObject *cls, PyObject *f,
14681505
Py_ssize_t nbytes;
14691506
int not_enough_bytes;
14701507

1508+
if(!Py_CHECKWRITE(self)){
1509+
return PyErr_WriteToImmutable(self);
1510+
}
1511+
14711512
if (n < 0) {
14721513
PyErr_SetString(PyExc_ValueError, "negative count");
14731514
return NULL;
@@ -1575,6 +1616,10 @@ array_array_fromlist(arrayobject *self, PyObject *list)
15751616
{
15761617
Py_ssize_t n;
15771618

1619+
if(!Py_CHECKWRITE(self)){
1620+
return PyErr_WriteToImmutable(self);
1621+
}
1622+
15781623
if (!PyList_Check(list)) {
15791624
PyErr_SetString(PyExc_TypeError, "arg must be list");
15801625
return NULL;
@@ -1636,6 +1681,11 @@ frombytes(arrayobject *self, Py_buffer *buffer)
16361681
{
16371682
int itemsize = self->ob_descr->itemsize;
16381683
Py_ssize_t n;
1684+
1685+
if(!Py_CHECKWRITE(self)){
1686+
return PyErr_WriteToImmutable(self);
1687+
}
1688+
16391689
if (buffer->itemsize != 1) {
16401690
PyBuffer_Release(buffer);
16411691
PyErr_SetString(PyExc_TypeError, "a bytes-like object is required");
@@ -1725,6 +1775,10 @@ array_array_fromunicode_impl(arrayobject *self, PyObject *ustr)
17251775
return NULL;
17261776
}
17271777

1778+
if(!Py_CHECKWRITE(self)){
1779+
return PyErr_WriteToImmutable(self);
1780+
}
1781+
17281782
Py_ssize_t ustr_length = PyUnicode_AsWideChar(ustr, NULL, 0);
17291783
assert(ustr_length > 0);
17301784
if (ustr_length > 1) {
@@ -2401,6 +2455,11 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
24012455
arrayobject* other;
24022456
int itemsize;
24032457

2458+
if(!Py_CHECKWRITE(self)){
2459+
PyErr_WriteToImmutable(self);
2460+
return -1;
2461+
}
2462+
24042463
if (PyIndex_Check(item)) {
24052464
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
24062465

0 commit comments

Comments
 (0)