Description
The following should segfault on any 64 bit NumPy:
a = np.ones(20)[::2]
a.reshape(2, 13, 419, 691, 823, 2977518503)
The trick is that, due to overflow:
>>> (np.int64(2) * np.int64(13) * np.int64(419) * np.int64(691) * np.int64(823) *
... np.int64(2977518503))
10
so the sizes of the arrays actually "match."
The values have been found by factoring 2**63 + 5
, then adding the leading 2 factor to make the whole result positive after overflow. For 32 bit systems, this should do the trick (untested):
a = np.ones(20)[::2]
a.reshape(2, 7, 7, 43826197)
The slicing of a
is needed to have a non-contiguous array, so that the code of PyArray_NewShape
calls _attempt_nocopy_reshape
. Trying the same with np.ones(10)
gives a proper "array too big" error.
There are computations of array size without proper overflow checking both in _attempt_nocopy_reshape
and _fix_unknown_dimension
. It may be enough to fix the check in _fix_unknown_dimension
, as an error there will prevent _attempt_nocopy_reshape
from being reachable, although it would be good to then remove the redundant size match check and document that it depends on the sizes actually matching. A test with the above examples should keep us safe from ignoring our own comments in the code.
And that's as far as I have gone into debugging this, will probably try fixing it over Easter if no one beats me to it.