diff options
-rw-r--r-- | Objects/listobject.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c index 3d4a187..fa26444 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -208,6 +208,19 @@ PyList_Size(PyObject *op) return Py_SIZE(op); } +static inline int +valid_index(Py_ssize_t i, Py_ssize_t limit) +{ + /* The cast to size_t lets us use just a single comparison + to check whether i is in the range: 0 <= i < limit. + + See: Section 14.2 "Bounds Checking" in the Agner Fog + optimization manual found at: + https://www.agner.org/optimize/optimizing_cpp.pdf + */ + return (size_t) i < (size_t) limit; +} + static PyObject *indexerr = NULL; PyObject * @@ -217,7 +230,7 @@ PyList_GetItem(PyObject *op, Py_ssize_t i) PyErr_BadInternalCall(); return NULL; } - if (i < 0 || i >= Py_SIZE(op)) { + if (!valid_index(i, Py_SIZE(op))) { if (indexerr == NULL) { indexerr = PyUnicode_FromString( "list index out of range"); @@ -240,7 +253,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i, PyErr_BadInternalCall(); return -1; } - if (i < 0 || i >= Py_SIZE(op)) { + if (!valid_index(i, Py_SIZE(op))) { Py_XDECREF(newitem); PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); @@ -426,7 +439,7 @@ list_contains(PyListObject *a, PyObject *el) static PyObject * list_item(PyListObject *a, Py_ssize_t i) { - if (i < 0 || i >= Py_SIZE(a)) { + if (!valid_index(i, Py_SIZE(a))) { if (indexerr == NULL) { indexerr = PyUnicode_FromString( "list index out of range"); @@ -749,7 +762,7 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n) static int list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v) { - if (i < 0 || i >= Py_SIZE(a)) { + if (!valid_index(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); return -1; @@ -996,7 +1009,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) } if (index < 0) index += Py_SIZE(self); - if (index < 0 || index >= Py_SIZE(self)) { + if (!valid_index(index, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } |