Commit c7ea3c1b authored by da-woods's avatar da-woods Committed by GitHub

Fix crash on memoryview self-assignments (GH-3874)

* Fixed crash on memoryview self-assignment
* Rename memoryview decref function to match what it does
parent a8d806be
......@@ -414,7 +414,7 @@ class FusedCFuncDefNode(StatListNode):
if itemsize == -1 or itemsize == {{sizeof_dtype}}:
memslice = {{coerce_from_py_func}}(arg, 0)
if memslice.memview:
__PYX_XDEC_MEMVIEW(&memslice, 1)
__PYX_XCLEAR_MEMVIEW(&memslice, 1)
# print 'found a match for the buffer through format parsing'
%s
break
......@@ -493,7 +493,7 @@ class FusedCFuncDefNode(StatListNode):
ctypedef struct {{memviewslice_cname}}:
void *memview
void __PYX_XDEC_MEMVIEW({{memviewslice_cname}} *, int have_gil)
void __PYX_XCLEAR_MEMVIEW({{memviewslice_cname}} *, int have_gil)
bint __pyx_memoryview_check(object)
""")
......
......@@ -100,6 +100,12 @@ def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code,
def put_assign_to_memviewslice(lhs_cname, rhs, rhs_cname, memviewslicetype, code,
have_gil=False, first_assignment=False):
if lhs_cname == rhs_cname:
# self assignment is tricky because memoryview xdecref clears the memoryview
# thus invalidating both sides of the assignment. Therefore make it actually do nothing
code.putln("/* memoryview self assignment no-op */")
return
if not first_assignment:
code.put_xdecref(lhs_cname, memviewslicetype,
have_gil=have_gil)
......
......@@ -1841,7 +1841,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("Py_CLEAR(p->%s.obj);" % entry.cname)
if cclass_entry.cname == '__pyx_memoryviewslice':
code.putln("__PYX_XDEC_MEMVIEW(&p->from_slice, 1);")
code.putln("__PYX_XCLEAR_MEMVIEW(&p->from_slice, 1);")
code.putln("return 0;")
code.putln("}")
......
......@@ -1099,7 +1099,7 @@ class MemoryViewSliceType(PyrexType):
# decref however did look to always apply for memoryview slices
# with "have_gil" set to True by default
def generate_xdecref(self, code, cname, nanny, have_gil):
code.putln("__PYX_XDEC_MEMVIEW(&%s, %d);" % (cname, int(have_gil)))
code.putln("__PYX_XCLEAR_MEMVIEW(&%s, %d);" % (cname, int(have_gil)))
def generate_decref(self, code, cname, nanny, have_gil):
# Fall back to xdecref since we don't care to have a separate decref version for this.
......
......@@ -56,7 +56,7 @@ cdef extern from *:
Py_ssize_t suboffsets[{{max_dims}}]
void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
void __PYX_XDEC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
void __PYX_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
ctypedef struct __pyx_buffer "Py_buffer":
PyObject *obj
......@@ -987,7 +987,7 @@ cdef class _memoryviewslice(memoryview):
cdef int (*to_dtype_func)(char *, object) except 0
def __dealloc__(self):
__PYX_XDEC_MEMVIEW(&self.from_slice, 1)
__PYX_XCLEAR_MEMVIEW(&self.from_slice, 1)
cdef convert_item_to_object(self, char *itemp):
if self.to_object_func != NULL:
......
......@@ -113,9 +113,9 @@ static CYTHON_INLINE int __pyx_sub_acquisition_count_locked(
#define __pyx_get_slice_count_pointer(memview) (memview->acquisition_count_aligned_p)
#define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview))
#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__)
#define __PYX_XDEC_MEMVIEW(slice, have_gil) __Pyx_XDEC_MEMVIEW(slice, have_gil, __LINE__)
#define __PYX_XCLEAR_MEMVIEW(slice, have_gil) __Pyx_XCLEAR_MEMVIEW(slice, have_gil, __LINE__)
static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *, int, int);
static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *, int, int);
static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *, int, int);
/////////////// MemviewSliceIndex.proto ///////////////
......@@ -512,7 +512,7 @@ __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno)
}
}
static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice,
int have_gil, int lineno) {
__pyx_atomic_int_type old_acquisition_count;
struct {{memview_struct_name}} *memview = memslice->memview;
......
......@@ -157,6 +157,7 @@ def assignmvs():
cdef int[:] mv3
mv1 = array((10,), itemsize=sizeof(int), format='i')
mv2 = mv1
mv1 = mv1
mv1 = mv2
mv3 = mv2
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment