Skip to content

Commit 806146f

Browse files
committed
chore: resolve review comment
1 parent dc4af2a commit 806146f

File tree

2 files changed

+21
-16
lines changed

2 files changed

+21
-16
lines changed

Lib/test/test_array.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,15 +1367,15 @@ def test_frombytearray(self):
13671367
b = array.array(self.typecode, a)
13681368
self.assertEqual(a, b)
13691369

1370-
def test_tofile_use_after_free(self):
1371-
CHUNK = 64 * 1024
1372-
victim = array.array('B', b'\0' * (CHUNK * 2))
1370+
def test_tofile_concurrent_mutation(self):
1371+
BLOCKSIZE = 64 * 1024
1372+
victim = array.array('B', b'\0' * (BLOCKSIZE * 2))
13731373

13741374
class Writer:
1375-
armed = True
1375+
cleared = False
13761376
def write(self, data):
1377-
if Writer.armed:
1378-
Writer.armed = False
1377+
if not self.cleared:
1378+
self.cleared = True
13791379
victim.clear()
13801380
return 0
13811381

Modules/arraymodule.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,29 +1589,36 @@ array_array_tofile_impl(arrayobject *self, PyTypeObject *cls, PyObject *f)
15891589
{
15901590
/* Write 64K blocks at a time */
15911591
/* XXX Make the block size settable */
1592-
int BLOCKSIZE = 64*1024;
1593-
Py_ssize_t offset = 0;
1592+
const Py_ssize_t BLOCKSIZE = 64*1024;
1593+
const Py_ssize_t itemsize = self->ob_descr->itemsize;
1594+
1595+
Py_ssize_t nbytes = Py_SIZE(self) * itemsize;
1596+
Py_ssize_t nblocks = (nbytes + BLOCKSIZE - 1) / BLOCKSIZE;
15941597

15951598
if (Py_SIZE(self) == 0)
15961599
goto done;
15971600

15981601
array_state *state = get_array_state_by_class(cls);
15991602
assert(state != NULL);
16001603

1601-
while (1) {
1604+
for (Py_ssize_t i = 0; i < nblocks; i++) {
16021605
if (self->ob_item == NULL || Py_SIZE(self) == 0) {
16031606
break;
16041607
}
16051608

1606-
Py_ssize_t current_nbytes = Py_SIZE(self) * self->ob_descr->itemsize;
1609+
if (Py_SIZE(self) > PY_SSIZE_T_MAX / itemsize) {
1610+
return PyErr_NoMemory();
1611+
}
16071612

1613+
Py_ssize_t current_nbytes = Py_SIZE(self) * itemsize;
1614+
const Py_ssize_t offset = i * BLOCKSIZE;
16081615
if (offset >= current_nbytes) {
16091616
break;
16101617
}
16111618

1612-
Py_ssize_t size = BLOCKSIZE;
1613-
if (offset + size > current_nbytes) {
1614-
size = current_nbytes - offset;
1619+
Py_ssize_t size = current_nbytes - offset;
1620+
if (size > BLOCKSIZE) {
1621+
size = BLOCKSIZE;
16151622
}
16161623

16171624
char* ptr = self->ob_item + offset;
@@ -1625,9 +1632,7 @@ array_array_tofile_impl(arrayobject *self, PyTypeObject *cls, PyObject *f)
16251632
Py_DECREF(bytes);
16261633
if (res == NULL)
16271634
return NULL;
1628-
Py_DECREF(res);
1629-
1630-
offset += size;
1635+
Py_DECREF(res); /* drop write result */
16311636
}
16321637

16331638
done:

0 commit comments

Comments
 (0)