8000 Merge pull request #7816 from charris/backport-7463 · numpy/numpy@74cf40f · GitHub
[go: up one dir, main page]

Skip to content

Commit 74cf40f

Browse files
authored
Merge pull request #7816 from charris/backport-7463
Backport 7463
2 parents c3992a0 + 66be3ab commit 74cf40f

File tree

4 files changed

+40
-25
lines changed

4 files changed

+40
-25
lines changed

numpy/core/src/multiarray/ctors.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,7 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
901901
{
902902
PyArrayObject_fields *fa;
903903
int i;
904-
size_t sd;
905-
npy_intp size;
904+
npy_intp nbytes;
906905

907906
if (descr->subarray) {
908907
PyObject *ret;
@@ -929,10 +928,9 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
929928
return NULL;
930929
}
931930

932-
/* Check dimensions */
933-
size = 1;
934-
sd = (size_t) descr->elsize;
935-
if (sd == 0) {
931+
/* Check datatype element size */
932+
nbytes = descr->elsize;
933+
if (nbytes == 0) {
936934
if (!PyDataType_ISSTRING(descr)) {
937935
PyErr_SetString(PyExc_TypeError, "Empty data-type");
938936
Py_DECREF(descr);
@@ -943,13 +941,14 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
943941
return NULL;
944942
}
945943
if (descr->type_num == NPY_STRING) {
946-
sd = descr->elsize = 1;
944+
nbytes = descr->elsize = 1;
947945
}
948946
else {
949-
sd = descr->elsize = sizeof(npy_ucs4);
947+
nbytes = descr->elsize = sizeof(npy_ucs4);
950948
}
951949
}
952950

951+
/* Check dimensions and multiply them to nbytes */
953952
for (i = 0; i < nd; i++) {
954953
npy_intp dim = dims[i];
955954

@@ -974,9 +973,10 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
974973
* multiplying the dimensions together to get the total size of the
975974
* array.
976975
*/
977-
if (npy_mul_with_overflow_intp(&size, size, dim)) {
976+
if (npy_mul_with_overflow_intp(&nbytes, nbytes, dim)) {
978977
PyErr_SetString(PyExc_ValueError,
979-
"array is too big.");
978+
"array is too big; `arr.size * arr.dtype.itemsize` "
979+
"is larger than the maximum possible size.");
980980
Py_DECREF(descr);
981981
return NULL;
982982
}
@@ -1015,17 +1015,16 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
10151015
}
10161016
fa->strides = fa->dimensions + nd;
10171017
memcpy(fa->dimensions, dims, sizeof(npy_intp)*nd);
1018-
if (strides == NULL) { /* fill it in */
1019-
sd = _array_fill_strides(fa->strides, dims, nd, sd,
1020-
flags, &(fa->flags));
1018+
if (strides == NULL) { /* fill it in */
1019+
_array_fill_strides(fa->strides, dims, nd, descr->elsize,
1020+
flags, &(fa->flags));
10211021
}
10221022
else {
10231023
/*
10241024
* we allow strides even when we create
10251025
* the memory, but be careful with this...
10261026
*/
10271027
memcpy(fa->strides, strides, sizeof(npy_intp)*nd);
1028-
sd *= size;
10291028
}
10301029
}
10311030
else {
@@ -1039,19 +1038,18 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
10391038
* e.g. shape=(0,) -- otherwise buffer exposure
10401039
* (a.data) doesn't work as it should.
10411040
*/
1042-
1043-
if (sd == 0) {
1044-
sd = descr->elsize;
1041+
if (nbytes == 0) {
1042+
nbytes = descr->elsize;
10451043
}
10461044
/*
10471045
* It is bad to have unitialized OBJECT pointers
10481046
* which could also be sub-fields of a VOID array
10491047
*/
10501048
if (zeroed || PyDataType_FLAGCHK(descr, NPY_NEEDS_INIT)) {
1051-
data = npy_alloc_cache_zero(sd);
1049+
data = npy_alloc_cache_zero(nbytes);
10521050
}
10531051
else {
1054-
data = npy_alloc_cache(sd);
1052+
data = npy_alloc_cache(nbytes);
10551053
}
10561054
if (data == NULL) {
10571055
PyErr_NoMemory();
@@ -3772,9 +3770,11 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count)
37723770
* If data is not given but created here, then flags will be NPY_ARRAY_DEFAULT
37733771
* and a non-zero flags argument can be used to indicate a FORTRAN style
37743772
* array is desired.
3773+
*
3774+
* Dimensions and itemsize must have been checked for validity.
37753775
*/
37763776

3777-
NPY_NO_EXPORT size_t
3777+
NPY_NO_EXPORT void
37783778
_array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize,
37793779
int inflag, int *objflags)
37803780
{
@@ -3845,7 +3845,7 @@ _array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize,
38453845
*objflags |= (NPY_ARRAY_C_CONTIGUOUS|NPY_ARRAY_F_CONTIGUOUS);
38463846
}
38473847
}
3848-
return itemsize;
3848+
return;
38493849
}
38503850

38513851
/*

numpy/core/src/multiarray/ctors.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ PyArray_CopyAsFlat(PyArrayObject *dst, PyArrayObject *src,
5151
NPY_ORDER order);
5252

5353
/* FIXME: remove those from here */
54-
NPY_NO_EXPORT size_t
54+
NPY_NO_EXPORT void
5555
_array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize,
5656
int inflag, int *objflags);
5757

numpy/core/src/multiarray/shape.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape, int refcheck,
149149
}
150150

151151
/* make new_strides variable */
152-
sd = (size_t) PyArray_DESCR(self)->elsize;
153-
sd = (size_t) _array_fill_strides(new_strides, new_dimensions, new_nd, sd,
154-
PyArray_FLAGS(self), &(((PyArrayObject_fields *)self)->flags));
152+
_array_fill_strides(
153+
new_strides, new_dimensions, new_nd, PyArray_DESCR(self)->elsize,
154+
PyArray_FLAGS(self), &(((PyArrayObject_fields *)self)->flags));
155155
memmove(PyArray_DIMS(self), new_dimensions, new_nd*sizeof(npy_intp));
156156
memmove(PyArray_STRIDES(self), new_strides, new_nd*sizeof(npy_intp));
157157
Py_RETURN_NONE;

numpy/core/tests/test_multiarray.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,21 @@ def __len__(self):
730730
d = A([1,2,3])
731731
assert_equal(len(np.array(d)), 3)
732732

733+
def test_array_too_big(self):
734+
# Test that array creation succeeds for arrays addressable by intp
735+
# on the byte level and fails for too large arrays.
736+
buf = np.zeros(100)
737+
738+
max_bytes = np.iinfo(np.intp).max
739+
for dtype in ["intp", "S20", "b"]:
740+
dtype = np.dtype(dtype)
741+
itemsize = dtype.itemsize
742+
743+
np.ndarray(buffer=buf, strides=(0,),
744+
shape=(max_bytes//itemsize,), dtype=dtype)
745+
assert_raises(ValueError, np.ndarray, buffer=buf, strides=(0,),
746+
shape=(max_bytes//itemsize + 1,), dtype=dtype)
747+
733748

734749
class TestStructured(TestCase):
735750
def test_subarray_field_access(self):

0 commit comments

Comments
 (0)
0