Message303322
The following code:
from ctypes import *
from _testcapi import PY_SSIZE_T_MAX, LONG_MAX
if LONG_MAX == PY_SSIZE_T_MAX == (1 << 31) - 1:
class MyArray(Array):
_type_ = c_longlong
_length_ = 1 << 29
arr = MyArray()
for i in range(3):
arr[i] = i
for i in range(3):
print(arr[i])
Produces this output (on a 32bit Python on my Windows 10):
2
2
2
This is because PyCArrayType_new() (in Modules/_ctypes/_ctypes.c) raises a
"array too large" error in case (length * itemsize < 0). However, this
multiplication might also overflow to a non-negative number, e.g. to zero in
the code above.
PyCArrayType_new() then does:
stgdict->size = itemsize * length;
Array_ass_item() and Array_item() both do:
size = stgdict->size / stgdict->length;
offset = index * size;
So in the above code, the integer overflow caused the array to collapse to a
single element (the first element).
ISTM that we can fix this by changing the overflow detection logic to this:
assert(itemsize >= 0 && length >= 0);
array_size = itemsize * length;
if (itemsize && array_size / itemsize != length) {
PyErr_SetString(PyExc_OverflowError,
"array too large");
goto error;
}
The assertion is guaranteed to be true after #29843 is resolved. (I would open
a PR for #29843 soon.) |
|
Date |
User |
Action |
Args |
2017-09-29 10:39:58 | Oren Milman | set | recipients:
+ Oren Milman |
2017-09-29 10:39:58 | Oren Milman | set | messageid: <1506681598.22.0.213398074469.issue31637@psf.upfronthosting.co.za> |
2017-09-29 10:39:58 | Oren Milman | link | issue31637 messages |
2017-09-29 10:39:57 | Oren Milman | create | |
|