Skip to content

Commit d545dc4

Browse files
committed
more size guarding
1 parent 07c9c15 commit d545dc4

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

Modules/arraymodule.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ enum machine_format_code {
154154
static inline bool
155155
arraydata_size_valid(Py_ssize_t size, int itemsize)
156156
{
157-
return size <= (PY_SSIZE_T_MAX - (Py_ssize_t)sizeof(arraydata)) / itemsize;
157+
return size >= 0 &&
158+
size <= (PY_SSIZE_T_MAX - (Py_ssize_t)sizeof(arraydata)) / itemsize;
158159
}
159160

160161
static arraydata *
@@ -213,6 +214,7 @@ static int
213214
array_resize(arrayobject *self, Py_ssize_t newsize)
214215
{
215216
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
217+
assert(newsize >= 0);
216218

217219
if (self->ob_exports > 0 && newsize != Py_SIZE(self)) {
218220
PyErr_SetString(PyExc_BufferError,
@@ -267,6 +269,11 @@ array_resize(arrayobject *self, Py_ssize_t newsize)
267269
*/
268270

269271
size_t _new_size = (newsize >> 4) + (Py_SIZE(self) < 8 ? 3 : 7) + newsize;
272+
// Limit over-allocation to not overflow Py_ssize_t, newsize can't ever be
273+
// larger than this anyway.
274+
if (_new_size > PY_SSIZE_T_MAX) {
275+
_new_size = PY_SSIZE_T_MAX;
276+
}
270277
int itemsize = self->ob_descr->itemsize;
271278

272279
if (!arraydata_size_valid(_new_size, itemsize)) {
@@ -2116,7 +2123,13 @@ array_array_fromunicode_impl(arrayobject *self, PyObject *ustr)
21162123
if (ustr_length > 1) {
21172124
ustr_length--; /* trim trailing NUL character */
21182125
Py_ssize_t old_size = Py_SIZE(self);
2119-
if (array_resize(self, old_size + ustr_length) == -1) {
2126+
// if overflows PY_SSIZE_T_MAX arraydata_size_valid() will catch it
2127+
Py_ssize_t new_size = old_size + ustr_length;
2128+
2129+
if (!arraydata_size_valid(new_size, sizeof(wchar_t))) {
2130+
return PyErr_NoMemory();
2131+
}
2132+
if (array_resize(self, new_size) == -1) {
21202133
return NULL;
21212134
}
21222135

@@ -2128,9 +2141,10 @@ array_array_fromunicode_impl(arrayobject *self, PyObject *ustr)
21282141
else { // typecode == 'w'
21292142
Py_ssize_t ustr_length = PyUnicode_GetLength(ustr);
21302143
Py_ssize_t old_size = Py_SIZE(self);
2144+
// if overflows PY_SSIZE_T_MAX arraydata_size_valid() will catch it
21312145
Py_ssize_t new_size = old_size + ustr_length;
21322146

2133-
if (new_size < 0 || !arraydata_size_valid(new_size, sizeof(Py_UCS4))) {
2147+
if (!arraydata_size_valid(new_size, sizeof(Py_UCS4))) {
21342148
return PyErr_NoMemory();
21352149
}
21362150
if (array_resize(self, new_size) == -1) {

0 commit comments

Comments
 (0)