From: Stefan Behnel Date: Sat, 16 Mar 2013 14:46:46 +0000 (+0100) Subject: fix negative slice indices X-Git-Tag: 0.19b1~46 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c7d063ccb63a2c3462fbdd3c295500a5c580ef8d;p=platform%2Fupstream%2Fpython-cython.git fix negative slice indices --- diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c index 9f34f7e..1ac5cc5 100644 --- a/Cython/Utility/ObjectHandling.c +++ b/Cython/Utility/ObjectHandling.c @@ -427,15 +427,15 @@ static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, if (likely(m && m->sq_ass_item)) { if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { Py_ssize_t l = m->sq_length(o); - if (likely(l >= 0)) { - i += l; - } else { - // if length > max(Py_ssize_t), maybe the object can wrap around itself? - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_Clear(); - else - return -1; - } + if (likely(l >= 0)) { + i += l; + } else { + // if length > max(Py_ssize_t), maybe the object can wrap around itself? + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + PyErr_Clear(); + else + return -1; + } } return m->sq_ass_item(o, i, (PyObject *)NULL); } @@ -476,6 +476,25 @@ static CYTHON_INLINE PyObject* __Pyx_PySequence_GetObjectSlice( } else cstop = PY_SSIZE_T_MAX; } + if (unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { + Py_ssize_t l = ms->sq_length(obj); + if (likely(l >= 0)) { + if (cstop < 0) { + cstop += l; + if (cstop < 0) cstop = 0; + } + if (cstart < 0) { + cstart += l; + if (cstart < 0) cstart = 0; + } + } else { + // if length > max(Py_ssize_t), maybe the object can wrap around itself? + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + PyErr_Clear(); + else + return NULL; + } + } return ms->sq_slice(obj, cstart, cstop); } #endif diff --git a/tests/run/slice2.pyx b/tests/run/slice2.pyx index 7c7cd37..e638d1f 100644 --- a/tests/run/slice2.pyx +++ b/tests/run/slice2.pyx @@ -1,47 +1,74 @@ -def f(obj1, obj2, obj3, obj4): +def test_full(seq): """ >>> l = [1,2,3,4] - >>> f(1, l, 2, 3) + >>> test_full(l) [1, 2, 3, 4] - >>> l == f(1, l, 2, 3) + >>> l == test_full(l) True - >>> l is f(1, l, 2, 3) + >>> l is test_full(l) False - >>> try: f(1, 42, 2, 3) + >>> try: test_full(42) ... except TypeError: pass """ - obj1 = obj2[:] - return obj1 + obj = seq[:] + return obj -def g(obj1, obj2, obj3, obj4): +def test_start(seq, start): """ - >>> g(1, [1,2,3,4], 2, 3) + >>> test_start([1,2,3,4], 2) [3, 4] - >>> try: g(1, 42, 2, 3) + >>> test_start([1,2,3,4], 3) + [4] + >>> test_start([1,2,3,4], 4) + [] + >>> test_start([1,2,3,4], 8) + [] + >>> test_start([1,2,3,4], -3) + [2, 3, 4] + >>> test_start([1,2,3,4], -4) + [1, 2, 3, 4] + >>> test_start([1,2,3,4], -8) + [1, 2, 3, 4] + >>> test_start([1,2,3,4], 0) + [1, 2, 3, 4] + >>> try: test_start(42, 2, 3) ... except TypeError: pass """ - obj1 = obj2[obj3:] - return obj1 + obj = seq[start:] + return obj -def h(obj1, obj2, obj3, obj4): +def test_stop(seq, stop): """ - >>> h(1, [1,2,3,4], 2, 3) + >>> test_stop([1,2,3,4], 3) [1, 2, 3] - >>> try: h(1, 42, 2, 3) + >>> test_stop([1,2,3,4], -1) + [1, 2, 3] + >>> test_stop([1,2,3,4], -3) + [1] + >>> test_stop([1,2,3,4], -4) + [] + >>> test_stop([1,2,3,4], -8) + [] + >>> test_stop([1,2,3,4], 0) + [] + >>> try: test_stop(42, 3) ... except TypeError: pass """ - obj1 = obj2[:obj4] - return obj1 + obj = seq[:stop] + return obj -def j(obj1, obj2, obj3, obj4): +def test_start_and_stop(seq, start, stop): """ - >>> j(1, [1,2,3,4], 2, 3) + >>> l = [1,2,3,4] + >>> test_start_and_stop(l, 2, 3) [3] - >>> try: j(1, 42, 2, 3) + >>> test_start_and_stop(l, -3, -1) + [2, 3] + >>> try: test_start_and_stop(42, 2, 3) ... except TypeError: pass """ - obj1 = obj2[obj3:obj4] - return obj1 + obj = seq[start:stop] + return obj class A(object): pass