Skip to content

Commit 60f6e5b

Browse files
committed
fix and clean up array size checks everywhere
1 parent 05b1a91 commit 60f6e5b

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

Modules/arraymodule.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,16 @@ enum machine_format_code {
151151

152152
#define array_Check(op, state) PyObject_TypeCheck(op, state->ArrayType)
153153

154+
static inline bool
155+
arraydata_size_valid(Py_ssize_t size, int itemsize)
156+
{
157+
return size <= (PY_SSIZE_T_MAX - sizeof(arraydata)) / itemsize;
158+
}
159+
154160
static arraydata *
155161
arraydata_alloc(Py_ssize_t size, int itemsize)
156162
{
157-
assert(size <= PY_SSIZE_T_MAX / itemsize);
163+
assert(arraydata_size_valid(size, itemsize));
158164
Py_ssize_t bufsize = sizeof(arraydata) + size * itemsize;
159165
arraydata *data = (arraydata *)PyMem_Malloc(bufsize);
160166
if (data == NULL) {
@@ -265,7 +271,7 @@ array_resize(arrayobject *self, Py_ssize_t newsize)
265271

266272
/* XXX The following multiplication and division does not optimize away
267273
like it does for lists since the size is not known at compile time */
268-
if (_new_size > ((~(size_t)0) / itemsize)) {
274+
if (!arraydata_size_valid(_new_size, itemsize)) {
269275
PyErr_NoMemory();
270276
return -1;
271277
}
@@ -745,7 +751,7 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *des
745751
}
746752

747753
/* Check for overflow */
748-
if (size > PY_SSIZE_T_MAX / descr->itemsize) {
754+
if (!arraydata_size_valid(size, descr->itemsize)) {
749755
return PyErr_NoMemory();
750756
}
751757
op = (arrayobject *) type->tp_alloc(type, 0);
@@ -1368,7 +1374,7 @@ array_do_extend_lock_held(array_state *state, arrayobject *self, PyObject *bb)
13681374
return -1;
13691375
}
13701376
if ((Py_SIZE(self) > PY_SSIZE_T_MAX - Py_SIZE(b)) ||
1371-
((Py_SIZE(self) + Py_SIZE(b)) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
1377+
!arraydata_size_valid(Py_SIZE(self) + Py_SIZE(b), self->ob_descr->itemsize)) {
13721378
PyErr_NoMemory();
13731379
return -1;
13741380
}
@@ -1424,6 +1430,7 @@ array_inplace_repeat_lock_held(PyObject *op, Py_ssize_t n)
14241430
if (array_size > 0 && n != 1 ) {
14251431
if (n < 0)
14261432
n = 0;
1433+
// XXX This check below does nothing useful???
14271434
if ((self->ob_descr->itemsize != 0) &&
14281435
(array_size > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
14291436
return PyErr_NoMemory();
@@ -1848,15 +1855,15 @@ array_array_fromfile_impl(arrayobject *self, PyTypeObject *cls, PyObject *f,
18481855
/*[clinic end generated code: output=83a667080b345ebc input=3822e907c1c11f1a]*/
18491856
{
18501857
PyObject *b, *res;
1851-
Py_ssize_t itemsize = self->ob_descr->itemsize;
1858+
int itemsize = self->ob_descr->itemsize;
18521859
Py_ssize_t nbytes;
18531860
int not_enough_bytes;
18541861

18551862
if (n < 0) {
18561863
PyErr_SetString(PyExc_ValueError, "negative count");
18571864
return NULL;
18581865
}
1859-
if (n > PY_SSIZE_T_MAX / itemsize) {
1866+
if (!arraydata_size_valid(n, itemsize)) {
18601867
PyErr_NoMemory();
18611868
return NULL;
18621869
}
@@ -2048,7 +2055,7 @@ array_array_frombytes_impl(arrayobject *self, Py_buffer *buffer)
20482055
if (n > 0) {
20492056
Py_ssize_t old_size = Py_SIZE(self);
20502057
if ((n > PY_SSIZE_T_MAX - old_size) ||
2051-
((old_size + n) > PY_SSIZE_T_MAX / itemsize)) {
2058+
!arraydata_size_valid(old_size + n, itemsize)) {
20522059
return PyErr_NoMemory();
20532060
}
20542061
if (array_resize(self, old_size + n) == -1) {
@@ -2071,7 +2078,7 @@ static PyObject *
20712078
array_array_tobytes_impl(arrayobject *self)
20722079
/*[clinic end generated code: output=87318e4edcdc2bb6 input=c4d44d5499d2320f]*/
20732080
{
2074-
if (Py_SIZE(self) <= PY_SSIZE_T_MAX / self->ob_descr->itemsize) {
2081+
if (arraydata_size_valid(Py_SIZE(self), self->ob_descr->itemsize)) {
20752082
return PyBytes_FromStringAndSize(array_items_ptr(self),
20762083
Py_SIZE(self) * self->ob_descr->itemsize);
20772084
} else {
@@ -2125,7 +2132,7 @@ array_array_fromunicode_impl(arrayobject *self, PyObject *ustr)
21252132
Py_ssize_t old_size = Py_SIZE(self);
21262133
Py_ssize_t new_size = old_size + ustr_length;
21272134

2128-
if (new_size < 0 || (size_t)new_size > PY_SSIZE_T_MAX / sizeof(Py_UCS4)) {
2135+
if (new_size < 0 || !arraydata_size_valid(new_size, sizeof(Py_UCS4))) {
21292136
return PyErr_NoMemory();
21302137
}
21312138
if (array_resize(self, new_size) == -1) {

0 commit comments

Comments
 (0)