From fee84f22f341c18e8cdb5de07e08a99a3cbb2079 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Mon, 1 Nov 2010 19:33:18 +0100 Subject: [PATCH] fix ticket #578 by working around CPython bug 9834: crash in Py3.[0-1.2] when slicing non-sliceable objects --- Cython/Compiler/ExprNodes.py | 6 +++--- Cython/Compiler/ModuleNode.py | 19 +++++++++++++++++++ tests/run/slice2.pyx | 12 ++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 50ee5a74..72e7b5e3 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -2459,7 +2459,7 @@ class SliceIndexNode(ExprNode): code.error_goto_if_null(self.result(), self.pos))) else: code.putln( - "%s = PySequence_GetSlice(%s, %s, %s); %s" % ( + "%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % ( self.result(), self.base.py_result(), self.start_code(), @@ -2471,7 +2471,7 @@ class SliceIndexNode(ExprNode): self.generate_subexpr_evaluation_code(code) if self.type.is_pyobject: code.put_error_if_neg(self.pos, - "PySequence_SetSlice(%s, %s, %s, %s)" % ( + "__Pyx_PySequence_SetSlice(%s, %s, %s, %s)" % ( self.base.py_result(), self.start_code(), self.stop_code(), @@ -2508,7 +2508,7 @@ class SliceIndexNode(ExprNode): return self.generate_subexpr_evaluation_code(code) code.put_error_if_neg(self.pos, - "PySequence_DelSlice(%s, %s, %s)" % ( + "__Pyx_PySequence_DelSlice(%s, %s, %s)" % ( self.base.py_result(), self.start_code(), self.stop_code())) diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index a3650396..e00ccd07 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -593,6 +593,25 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln("#endif") code.put(""" +#if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300) + #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b) + #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value) + #define __Pyx_PySequence_DelSlice(obj, a, b) PySequence_DelSlice(obj, a, b) +#else + #define __Pyx_PySequence_GetSlice(obj, a, b) ((!(obj)) ? \\ + (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), (PyObject*)0) : \\ + (((obj)->ob_type->tp_as_mapping) ? (PySequence_GetSlice(obj, a, b)) : \\ + (PyErr_Format(PyExc_TypeError, "'%.200s' object is unsliceable", (obj)->ob_type->tp_name), (PyObject*)0))) + #define __Pyx_PySequence_SetSlice(obj, a, b, value) ((!(obj)) ? \\ + (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \\ + (((obj)->ob_type->tp_as_mapping) ? (PySequence_SetSlice(obj, a, b, value)) : \\ + (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice assignment", (obj)->ob_type->tp_name), -1))) + #define __Pyx_PySequence_DelSlice(obj, a, b) ((!(obj)) ? \\ + (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \\ + (((obj)->ob_type->tp_as_mapping) ? (PySequence_DelSlice(obj, a, b)) : \\ + (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice deletion", (obj)->ob_type->tp_name), -1))) +#endif + #if PY_MAJOR_VERSION >= 3 #define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func)) #endif diff --git a/tests/run/slice2.pyx b/tests/run/slice2.pyx index 29e3f999..0b510bd9 100644 --- a/tests/run/slice2.pyx +++ b/tests/run/slice2.pyx @@ -7,6 +7,9 @@ def f(obj1, obj2, obj3, obj4): True >>> l is f(1, l, 2, 3) False + >>> f(1, 42, 2, 3) + Traceback (most recent call last): + TypeError: 'int' object is unsliceable """ obj1 = obj2[:] return obj1 @@ -15,6 +18,9 @@ def g(obj1, obj2, obj3, obj4): """ >>> g(1, [1,2,3,4], 2, 3) [3, 4] + >>> g(1, 42, 2, 3) + Traceback (most recent call last): + TypeError: 'int' object is unsliceable """ obj1 = obj2[obj3:] return obj1 @@ -23,6 +29,9 @@ def h(obj1, obj2, obj3, obj4): """ >>> h(1, [1,2,3,4], 2, 3) [1, 2, 3] + >>> h(1, 42, 2, 3) + Traceback (most recent call last): + TypeError: 'int' object is unsliceable """ obj1 = obj2[:obj4] return obj1 @@ -31,6 +40,9 @@ def j(obj1, obj2, obj3, obj4): """ >>> j(1, [1,2,3,4], 2, 3) [3] + >>> j(1, 42, 2, 3) + Traceback (most recent call last): + TypeError: 'int' object is unsliceable """ obj1 = obj2[obj3:obj4] return obj1 -- 2.26.2