Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e6b8b19

Browse files
authored
Merge pull request #17421 from seberg/coercion-cache-leak-large-arrays
BUG: Fix memory leak in array-coercion error paths
2 parents 48896f5 + 0e4a4d4 commit e6b8b19

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

numpy/core/src/multiarray/array_coercion.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ npy_new_coercion_cache(
538538
cache = _coercion_cache_cache[_coercion_cache_num];
539539
}
540540
else {
541-
cache = PyObject_MALLOC(sizeof(coercion_cache_obj));
541+
cache = PyMem_Malloc(sizeof(coercion_cache_obj));
542542
}
543543
if (cache == NULL) {
544544
PyErr_NoMemory();
@@ -570,7 +570,7 @@ npy_unlink_coercion_cache(coercion_cache_obj *current)
570570
_coercion_cache_num++;
571571
}
572572
else {
573-
PyObject_FREE(current);
573+
PyMem_Free(current);
574574
}
575575
return next;
576576
}

numpy/core/src/multiarray/ctors.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ PyArray_AssignFromCache(PyArrayObject *self, coercion_cache_obj *cache) {
610610
PyErr_SetString(PyExc_RuntimeError,
611611
"Inconsistent object during array creation? "
612612
"Content of sequences changed (cache not consumed).");
613+
npy_free_coercion_cache(cache);
613614
return -1;
614615
}
615616
return 0;
@@ -1467,6 +1468,7 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
14671468
PyErr_SetString(PyExc_TypeError,
14681469
"WRITEBACKIFCOPY used for non-array input.");
14691470
Py_DECREF(dtype);
1471+
npy_free_coercion_cache(cache);
14701472
return NULL;
14711473
}
14721474

@@ -1475,6 +1477,7 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
14751477
&PyArray_Type, dtype, ndim, dims, NULL, NULL,
14761478
flags&NPY_ARRAY_F_CONTIGUOUS, NULL);
14771479
if (ret == NULL) {
1480+
npy_free_coercion_cache(cache);
14781481
return NULL;
14791482
}
14801483
if (cache == NULL) {

numpy/core/tests/test_array_coercion.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,3 +635,18 @@ def __array__(self):
635635
assert arr[()] is ArrayLike
636636
arr = np.array([ArrayLike])
637637
assert arr[0] is ArrayLike
638+
639+
@pytest.mark.skipif(
640+
np.dtype(np.intp).itemsize < 8, reason="Needs 64bit platform")
641+
def test_too_large_array_error_paths(self):
642+
"""Test the error paths, including for memory leaks"""
643+
arr = np.array(0, dtype="uint8")
644+
# Guarantees that a contiguous copy won't work:
645+
arr = np.broadcast_to(arr, 2**62)
646+
647+
for i in range(5):
648+
# repeat, to ensure caching cannot have an effect:
649+
with pytest.raises(MemoryError):
650+
np.array(arr)
651+
with pytest.raises(MemoryError):
652+
np.array([arr])

0 commit comments

Comments
 (0)