diff options
-rw-r--r-- | Cython/Utility/MemoryView_C.c | 2 | ||||
-rw-r--r-- | Cython/Utility/ObjectHandling.c | 8 | ||||
-rw-r--r-- | Cython/Utility/Optimize.c | 2 | ||||
-rw-r--r-- | Cython/Utility/StringTools.c | 16 | ||||
-rw-r--r-- | Cython/Utility/TypeConversion.c | 43 |
5 files changed, 43 insertions, 28 deletions
diff --git a/Cython/Utility/MemoryView_C.c b/Cython/Utility/MemoryView_C.c index b1bd74aff..b7bd6a04e 100644 --- a/Cython/Utility/MemoryView_C.c +++ b/Cython/Utility/MemoryView_C.c @@ -857,7 +857,7 @@ if (unlikely(__pyx_memoryview_slice_memviewslice( if ({{wraparound}} && (__pyx_tmp_idx < 0)) __pyx_tmp_idx += __pyx_tmp_shape; - if ({{boundscheck}} && (__pyx_tmp_idx < 0 || __pyx_tmp_idx >= __pyx_tmp_shape)) { + if ({{boundscheck}} && !__Pyx_is_valid_index(__pyx_tmp_idx, __pyx_tmp_shape)) { {{if not have_gil}} #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c index e388410a6..b147cb33e 100644 --- a/Cython/Utility/ObjectHandling.c +++ b/Cython/Utility/ObjectHandling.c @@ -398,7 +398,7 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ss if (wraparound & unlikely(i < 0)) { wrapped_i += Py{{type}}_GET_SIZE(o); } - if ((!boundscheck) || likely((0 <= wrapped_i) & (wrapped_i < Py{{type}}_GET_SIZE(o)))) { + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, Py{{type}}_GET_SIZE(o)))) { PyObject *r = Py{{type}}_GET_ITEM(o, wrapped_i); Py_INCREF(r); return r; @@ -416,7 +416,7 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS if (is_list || PyList_CheckExact(o)) { Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((!boundscheck) || (likely((n >= 0) & (n < PyList_GET_SIZE(o))))) { + if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { PyObject *r = PyList_GET_ITEM(o, n); Py_INCREF(r); return r; @@ -424,7 +424,7 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, } else if (PyTuple_CheckExact(o)) { Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely((n >= 0) & (n < PyTuple_GET_SIZE(o)))) { + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { PyObject *r = PyTuple_GET_ITEM(o, n); Py_INCREF(r); return r; @@ -482,7 +482,7 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObje #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS if (is_list || PyList_CheckExact(o)) { Py_ssize_t n = (!wraparound) ? i : ((likely(i >= 0)) ? i : i + PyList_GET_SIZE(o)); - if ((!boundscheck) || likely((n >= 0) & (n < PyList_GET_SIZE(o)))) { + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o)))) { PyObject* old = PyList_GET_ITEM(o, n); Py_INCREF(v); PyList_SET_ITEM(o, n, v); diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c index 4f4061a63..3d5be8f00 100644 --- a/Cython/Utility/Optimize.c +++ b/Cython/Utility/Optimize.c @@ -165,7 +165,7 @@ static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t if (cix < 0) { cix += size; } - if (likely(0 <= cix && cix < size)) { + if (likely(__Pyx_is_valid_index(cix, size))) { PyObject* v = PyList_GET_ITEM(L, cix); Py_SIZE(L) -= 1; size -= 1; diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c index 2489e6630..4862a25a5 100644 --- a/Cython/Utility/StringTools.c +++ b/Cython/Utility/StringTools.c @@ -331,7 +331,7 @@ static CYTHON_INLINE int __Pyx_GetItemInt_ByteArray_Fast(PyObject* string, Py_ss if (wraparound | boundscheck) { length = PyByteArray_GET_SIZE(string); if (wraparound & unlikely(i < 0)) i += length; - if ((!boundscheck) || likely((0 <= i) & (i < length))) { + if ((!boundscheck) || likely(__Pyx_is_valid_index(i, length))) { return (unsigned char) (PyByteArray_AS_STRING(string)[i]); } else { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); @@ -361,7 +361,7 @@ static CYTHON_INLINE int __Pyx_SetItemInt_ByteArray_Fast(PyObject* string, Py_ss if (wraparound | boundscheck) { length = PyByteArray_GET_SIZE(string); if (wraparound & unlikely(i < 0)) i += length; - if ((!boundscheck) || likely((0 <= i) & (i < length))) { + if ((!boundscheck) || likely(__Pyx_is_valid_index(i, length))) { PyByteArray_AS_STRING(string)[i] = (char) v; return 0; } else { @@ -394,7 +394,7 @@ static CYTHON_INLINE Py_UCS4 __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py if (wraparound | boundscheck) { length = __Pyx_PyUnicode_GET_LENGTH(ustring); if (wraparound & unlikely(i < 0)) i += length; - if ((!boundscheck) || likely((0 <= i) & (i < length))) { + if ((!boundscheck) || likely(__Pyx_is_valid_index(i, length))) { return __Pyx_PyUnicode_READ_CHAR(ustring, i); } else { PyErr_SetString(PyExc_IndexError, "string index out of range"); @@ -752,15 +752,15 @@ static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t i /////////////// bytes_index /////////////// static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t index, int check_bounds) { + if (index < 0) + index += PyBytes_GET_SIZE(bytes); if (check_bounds) { Py_ssize_t size = PyBytes_GET_SIZE(bytes); - if (unlikely(index >= size) | ((index < 0) & unlikely(index < -size))) { + if (unlikely(!__Pyx_is_valid_index(index, size))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return (char) -1; } } - if (index < 0) - index += PyBytes_GET_SIZE(bytes); return PyBytes_AS_STRING(bytes)[index]; } @@ -990,7 +990,7 @@ static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyO { // CPython calls PyNumber_Index() internally ival = __Pyx_PyIndex_AsSsize_t(value); - if (unlikely((ival < 0) | (ival > 255))) { + if (unlikely(!__Pyx_is_valid_index(ival, 256))) { if (ival == -1 && PyErr_Occurred()) return -1; goto bad_range; @@ -1012,7 +1012,7 @@ static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value) { PyObject *pyval, *retval; #if CYTHON_COMPILING_IN_CPYTHON - if (likely((value >= 0) & (value <= 255))) { + if (likely(__Pyx_is_valid_index(value, 256))) { Py_ssize_t n = Py_SIZE(bytearray); if (likely(n != PY_SSIZE_T_MAX)) { if (unlikely(PyByteArray_Resize(bytearray, n + 1) < 0)) diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c index aa38d7da1..796c8bed9 100644 --- a/Cython/Utility/TypeConversion.c +++ b/Cython/Utility/TypeConversion.c @@ -16,6 +16,14 @@ (is_signed || likely(v < (type)PY_SSIZE_T_MAX || \ v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + // Optimisation from Section 14.2 "Bounds Checking" in + // https://www.agner.org/optimize/optimizing_cpp.pdf + // See https://bugs.python.org/issue28397 + // The cast to unsigned effectively tests for "0 <= i < limit". + return (size_t) i < (size_t) limit; +} + // fast and unsafe abs(Py_ssize_t) that ignores the overflow for (-PY_SSIZE_T_MAX-1) #if defined (__cplusplus) && __cplusplus >= 201103L #include <cstdlib> @@ -529,18 +537,23 @@ static Py_UCS4 __Pyx__PyObject_AsPy_UCS4(PyObject*); /////////////// ObjectAsUCS4 /////////////// -static Py_UCS4 __Pyx__PyObject_AsPy_UCS4(PyObject* x) { - long ival; - ival = __Pyx_PyInt_As_long(x); - if (unlikely(ival < 0)) { +static Py_UCS4 __Pyx__PyObject_AsPy_UCS4_raise_error(long ival) { + if (ival < 0) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_OverflowError, "cannot convert negative value to Py_UCS4"); - return (Py_UCS4)-1; - } else if (unlikely(ival > 1114111)) { + } else { PyErr_SetString(PyExc_OverflowError, "value too large to convert to Py_UCS4"); - return (Py_UCS4)-1; + } + return (Py_UCS4)-1; +} + +static Py_UCS4 __Pyx__PyObject_AsPy_UCS4(PyObject* x) { + long ival; + ival = __Pyx_PyInt_As_long(x); + if (unlikely(!__Pyx_is_valid_index(ival, 1114111 + 1))) { + return __Pyx__PyObject_AsPy_UCS4_raise_error(ival); } return (Py_UCS4)ival; } @@ -582,14 +595,16 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) { #endif ival = __Pyx_PyInt_As_long(x); } - if (unlikely(ival < 0)) { - if (!PyErr_Occurred()) + if (unlikely(!__Pyx_is_valid_index(ival, maxval + 1))) { + if (ival < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_OverflowError, + "cannot convert negative value to Py_UNICODE"); + return (Py_UNICODE)-1; + } else { PyErr_SetString(PyExc_OverflowError, - "cannot convert negative value to Py_UNICODE"); - return (Py_UNICODE)-1; - } else if (unlikely(ival > maxval)) { - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to Py_UNICODE"); + "value too large to convert to Py_UNICODE"); + } return (Py_UNICODE)-1; } return (Py_UNICODE)ival; |