8000 BUG: double decref of dtype in failure codepath. Test and fix by charris · Pull Request #12812 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: double decref of dtype in failure codepath. Test and fix #12812

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions numpy/core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,11 @@ PyArray_FromInterface(PyObject *origin)
&PyArray_Type, dtype,
n, dims, NULL, data,
dataflags, NULL, base);
/*
* Ref to dtype was stolen by PyArray_NewFromDescrAndBase
* Prevent DECREFing dtype in fail codepath by setting to NULL
*/
dtype = NULL;
if (ret == NULL) {
goto fail;
}
Expand Down
52 changes: 34 additions & 18 deletions numpy/core/tests/test_multiarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -7009,12 +7009,11 @@ def test_multiarray_flags_not_writable_attribute_deletion(self):
assert_raises(AttributeError, delattr, a, s)


def test_array_interface():
# Test scalar coercion within the array interface
class TestArrayInterface():
class Foo(object):
def __init__(self, value):
self.value = value
self.iface = {'typestr': '=f8'}
self.iface = {'typestr': 'f8'}

def __float__(self):
return float(self.value)
Expand All @@ -7023,22 +7022,39 @@ def __float__(self):
def __array_interface__(self):
return self.iface


f = Foo(0.5)
assert_equal(np.array(f), 0.5)
assert_equal(np.array([f]), [0.5])
assert_equal(np.array([f, f]), [0.5, 0.5])
assert_equal(np.array(f).dtype, np.dtype('=f8'))
# Test various shape definitions
f.iface['shape'] = ()
assert_equal(np.array(f), 0.5)
f.iface['shape'] = None
assert_raises(TypeError, np.array, f)
f.iface['shape'] = (1, 1)
assert_equal(np.array(f), [[0.5]])
f.iface['shape'] = (2,)
assert_raises(ValueError, np.array, f)

# test scalar with no shape

@pytest.mark.parametrize('val, iface, expected', [
(f, {}, 0.5),
([f], {}, [0.5]),
([f, f], {}, [0.5, 0.5]),
(f, {'shape': ()}, 0.5),
(f, {'shape': None}, TypeError),
(f, {'shape': (1, 1)}, [[0.5]]),
(f, {'shape': (2,)}, ValueError),
(f, {'strides': ()}, 0.5),
(f, {'strides': (2,)}, ValueError),
(f, {'strides': 16}, TypeError),
])
def test_scalar_interface(self, val, iface, expected):
# Test scalar coercion within the array interface
self.f.iface = {'typestr': 'f8'}
self.f.iface.update(iface)
if HAS_REFCOUNT:
pre_cnt = sys.getrefcount(np.dtype('f8'))
if isinstance(expected, type):
assert_raises(expected, np.array, val)
else:
result = np.array(val)
assert_equal(np.array(val), expected)
assert result.dtype == 'f8'
del result
if HAS_REFCOUNT:
post_cnt = sys.getrefcount(np.dtype('f8'))
assert_equal(pre_cnt, post_cnt)

def test_interface_no_shape():
class ArrayLike(object):
array = np.array(1)
__array_interface__ = array.__array_interface__
Expand Down
0