diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2022-07-03 00:23:31 -0700 |
---|---|---|
committer | da-woods <dw-git@d-woods.co.uk> | 2022-07-03 08:32:13 +0100 |
commit | 98cebe4dedb52550ce621cf9338283dd7262ea83 (patch) | |
tree | 4558e45e1818b20a33214aad3a506f9f1c5de03e /tests | |
parent | 5c900c59d03f23f7329d6e68e114e4a277112916 (diff) | |
download | cython-98cebe4dedb52550ce621cf9338283dd7262ea83.tar.gz |
BUG: Fortify object buffers against included NULLs (#4859)
* BUG: Fortify object buffers against included NULLs
While NumPy tends to not actively create object buffers initialized
only with NULL (rather than filled with None), at least older versions
of NumPy did do that. And NumPy guards against this.
This guards against embedded NULLs in object buffers interpreting
a NULL as None (and anticipating a NULL value also when setting
the buffer for reference count purposes).
Closes gh-4858
Diffstat (limited to 'tests')
-rw-r--r-- | tests/buffers/bufaccess.pyx | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/tests/buffers/bufaccess.pyx b/tests/buffers/bufaccess.pyx index 8761e6eb9..2a5e84185 100644 --- a/tests/buffers/bufaccess.pyx +++ b/tests/buffers/bufaccess.pyx @@ -1005,6 +1005,51 @@ def assign_to_object(object[object] buf, int idx, obj): buf[idx] = obj @testcase +def check_object_nulled_1d(MockBuffer[object, ndim=1] buf, int idx, obj): + """ + See comments on printbuf_object above. + + >>> a = object() + >>> rc1 = get_refcount(a) + >>> A = ObjectMockBuffer(None, [a, a]) + >>> check_object_nulled_1d(A, 0, a) + >>> decref(a) # new reference "added" to A + >>> check_object_nulled_1d(A, 1, a) + >>> decref(a) + >>> A = ObjectMockBuffer(None, [a, a, a, a], strides=(2,)) + >>> check_object_nulled_1d(A, 0, a) # only 0 due to stride + >>> decref(a) + >>> get_refcount(a) == rc1 + True + """ + cdef void **data = <void **>buf.buffer + data[idx] = NULL + res = buf[idx] # takes None + buf[idx] = obj + return res + +@testcase +def check_object_nulled_2d(MockBuffer[object, ndim=2] buf, int idx1, int idx2, obj): + """ + See comments on printbuf_object above. + + >>> a = object() + >>> rc1 = get_refcount(a) + >>> A = ObjectMockBuffer(None, [a, a, a, a], shape=(2, 2)) + >>> check_object_nulled_2d(A, 0, 0, a) + >>> decref(a) # new reference "added" to A + >>> check_object_nulled_2d(A, 1, 1, a) + >>> decref(a) + >>> get_refcount(a) == rc1 + True + """ + cdef void **data = <void **>buf.buffer + data[idx1 + 2*idx2] = NULL + res = buf[idx1, idx2] # takes None + buf[idx1, idx2] = obj + return res + +@testcase def assign_temporary_to_object(object[object] buf): """ See comments on printbuf_object above. |