From 6d3e970b06c587c34e587a32945734a3876d6844 Mon Sep 17 00:00:00 2001 From: Lukas Geiger Date: Thu, 6 Jun 2024 23:19:26 +0100 Subject: [PATCH] Reduce number of compares in index range checks --- Include/internal/pycore_abstract.h | 13 ++++++++++++ Modules/_ctypes/_ctypes.c | 5 +++-- Modules/_elementtree.c | 5 +++-- Modules/_sre/sre.c | 3 ++- Modules/arraymodule.c | 9 ++++---- Modules/mmapmodule.c | 12 +++++------ Objects/bytearrayobject.c | 12 +++++------ Objects/bytes_methods.c | 4 ++-- Objects/bytesobject.c | 13 ++++++------ Objects/dictobject.c | 5 +++-- Objects/listobject.c | 33 +++++++++--------------------- Objects/memoryobject.c | 4 ++-- Objects/tupleobject.c | 8 ++++---- Objects/unicodeobject.c | 8 ++++---- Python/optimizer.c | 3 ++- 15 files changed, 71 insertions(+), 66 deletions(-) diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h index 3cc0afac4bd5b4..789eaea09555dd 100644 --- a/Include/internal/pycore_abstract.h +++ b/Include/internal/pycore_abstract.h @@ -21,6 +21,19 @@ PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); extern int _PyObject_HasLen(PyObject *o); +static inline int +_Py_ValidIndex(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; +} + /* === Sequence protocol ================================================ */ #define PY_ITERSEARCH_COUNT 1 diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 1d9534671a4ee8..be6a5aedd014ad 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -106,6 +106,7 @@ bytes(cdata) # include #endif +#include "pycore_abstract.h" // _Py_ValidIndex() #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _Py_EnterRecursiveCall() #ifdef MS_WIN32 @@ -4645,7 +4646,7 @@ Array_item(PyObject *myself, Py_ssize_t index) CDataObject *self = (CDataObject *)myself; Py_ssize_t offset, size; - if (index < 0 || index >= self->b_length) { + if (!_Py_ValidIndex(index, self->b_length)) { PyErr_SetString(PyExc_IndexError, "invalid index"); return NULL; @@ -4800,7 +4801,7 @@ Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) } assert(stginfo); /* Cannot be NULL for array object instances */ - if (index < 0 || index >= stginfo->length) { + if (!_Py_ValidIndex(index, stginfo->length)) { PyErr_SetString(PyExc_IndexError, "invalid index"); return -1; diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index b11983d2caa2d1..caa88f4a135cca 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -16,6 +16,7 @@ #endif #include "Python.h" +#include "pycore_abstract.h" // _Py_ValidIndex() #include "pycore_import.h" // _PyImport_GetModuleAttrString() #include "pycore_pyhash.h" // _Py_HashSecret @@ -1486,7 +1487,7 @@ element_getitem(PyObject* self_, Py_ssize_t index) { ElementObject* self = (ElementObject*) self_; - if (!self->extra || index < 0 || index >= self->extra->length) { + if (!self->extra || !_Py_ValidIndex(index, self->extra->length)) { PyErr_SetString( PyExc_IndexError, "child index out of range" @@ -1738,7 +1739,7 @@ element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item) Py_ssize_t i; PyObject* old; - if (!self->extra || index < 0 || index >= self->extra->length) { + if (!self->extra || !_Py_ValidIndex(index, self->extra->length)) { PyErr_SetString( PyExc_IndexError, "child assignment index out of range"); diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index c1eff63d921de9..298488eaa121a6 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -39,6 +39,7 @@ static const char copyright[] = " SRE 2.2.2 Copyright (c) 1997-2002 by Secret Labs AB "; #include "Python.h" +#include "pycore_abstract.h" // _Py_ValidIndex() #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION #include "pycore_dict.h" // _PyDict_Next() #include "pycore_long.h" // _PyLong_GetZero() @@ -2208,7 +2209,7 @@ match_getindex(MatchObject* self, PyObject* index) } } } - if (i < 0 || i >= self->groups) { + if (!_Py_ValidIndex(i, self->groups)) { /* raise IndexError if we were given a bad group number */ if (!PyErr_Occurred()) { PyErr_SetString(PyExc_IndexError, "no such group"); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index e6c84d588be98b..1cba1a78b33b7a 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -8,6 +8,7 @@ #endif #include "Python.h" +#include "pycore_abstract.h" // _Py_ValidIndex() #include "pycore_bytesobject.h" // _PyBytes_Repeat #include "pycore_call.h" // _PyObject_CallMethod() #include "pycore_ceval.h" // _PyEval_GetBuiltin() @@ -851,7 +852,7 @@ array_length(arrayobject *a) static PyObject * array_item(arrayobject *a, Py_ssize_t i) { - if (i < 0 || i >= Py_SIZE(a)) { + if (!_Py_ValidIndex(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "array index out of range"); return NULL; } @@ -1028,7 +1029,7 @@ array_del_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) static int array_ass_item(arrayobject *a, Py_ssize_t i, PyObject *v) { - if (i < 0 || i >= Py_SIZE(a)) { + if (!_Py_ValidIndex(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); return -1; @@ -1311,7 +1312,7 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i) } if (i < 0) i += Py_SIZE(self); - if (i < 0 || i >= Py_SIZE(self)) { + if (!_Py_ValidIndex(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } @@ -2502,7 +2503,7 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) return -1; if (i < 0) i += Py_SIZE(self); - if (i < 0 || i >= Py_SIZE(self)) { + if (!_Py_ValidIndex(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); return -1; diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 99a85e9e49ad47..99e9c8dc6cd2b5 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -23,7 +23,7 @@ #endif #include -#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t() +#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t(), _Py_ValidIndex() #include "pycore_bytesobject.h" // _PyBytes_Find() #include "pycore_fileutils.h" // _Py_stat_struct @@ -1131,7 +1131,7 @@ mmap_madvise_method(mmap_object *self, PyObject *args) return NULL; } - if (start < 0 || start >= self->size) { + if (!_Py_ValidIndex(start, self->size)) { PyErr_SetString(PyExc_ValueError, "madvise start out of bounds"); return NULL; } @@ -1229,7 +1229,7 @@ static PyObject * mmap_item(mmap_object *self, Py_ssize_t i) { CHECK_VALID(NULL); - if (i < 0 || i >= self->size) { + if (!_Py_ValidIndex(i, self->size)) { PyErr_SetString(PyExc_IndexError, "mmap index out of range"); return NULL; } @@ -1251,7 +1251,7 @@ mmap_subscript(mmap_object *self, PyObject *item) return NULL; if (i < 0) i += self->size; - if (i < 0 || i >= self->size) { + if (!_Py_ValidIndex(i, self->size)) { PyErr_SetString(PyExc_IndexError, "mmap index out of range"); return NULL; @@ -1309,7 +1309,7 @@ mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v) const char *buf; CHECK_VALID(-1); - if (i < 0 || i >= self->size) { + if (!_Py_ValidIndex(i, self->size)) { PyErr_SetString(PyExc_IndexError, "mmap index out of range"); return -1; } @@ -1349,7 +1349,7 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) return -1; if (i < 0) i += self->size; - if (i < 0 || i >= self->size) { + if (!_Py_ValidIndex(i, self->size)) { PyErr_SetString(PyExc_IndexError, "mmap index out of range"); return -1; diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 80679f93cd4c13..039296aaebc58b 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1,7 +1,7 @@ /* PyByteArray (bytearray) implementation */ #include "Python.h" -#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_abstract.h" // _PyIndex_Check(), _Py_ValidIndex() #include "pycore_bytes_methods.h" #include "pycore_bytesobject.h" #include "pycore_ceval.h" // _PyEval_GetBuiltin() @@ -359,7 +359,7 @@ bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count) static PyObject * bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i) { - if (i < 0 || i >= Py_SIZE(self)) { + if (!_Py_ValidIndex(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return NULL; } @@ -378,7 +378,7 @@ bytearray_subscript(PyByteArrayObject *self, PyObject *index) if (i < 0) i += PyByteArray_GET_SIZE(self); - if (i < 0 || i >= Py_SIZE(self)) { + if (!_Py_ValidIndex(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return NULL; } @@ -573,7 +573,7 @@ bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) i += Py_SIZE(self); } - if (i < 0 || i >= Py_SIZE(self)) { + if (!_Py_ValidIndex(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return -1; } @@ -613,7 +613,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu i += PyByteArray_GET_SIZE(self); } - if (i < 0 || i >= Py_SIZE(self)) { + if (!_Py_ValidIndex(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return -1; } @@ -1911,7 +1911,7 @@ bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index) } if (index < 0) index += Py_SIZE(self); - if (index < 0 || index >= Py_SIZE(self)) { + if (!_Py_ValidIndex(index, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index 981aa57164385e..c4bef8e3ca63b9 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -1,5 +1,5 @@ #include "Python.h" -#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_abstract.h" // _PyIndex_Check(), _Py_ValidIndex() #include "pycore_bytes_methods.h" PyDoc_STRVAR_shared(_Py_isspace__doc__, @@ -660,7 +660,7 @@ _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg) PyBuffer_Release(&varg); return pos >= 0; } - if (ival < 0 || ival >= 256) { + if (!_Py_ValidIndex(ival, 256)) { PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); return -1; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 459df6ceacf3a8..ae37fdb600b6dd 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1,7 +1,7 @@ /* bytes object implementation */ #include "Python.h" -#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_abstract.h" // _PyIndex_Check(), _Py_ValidIndex() #include "pycore_bytes_methods.h" // _Py_bytes_startswith() #include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_Repeat() #include "pycore_call.h" // _PyObject_CallNoArgs() @@ -1506,7 +1506,7 @@ bytes_contains(PyObject *self, PyObject *arg) static PyObject * bytes_item(PyBytesObject *a, Py_ssize_t i) { - if (i < 0 || i >= Py_SIZE(a)) { + if (!_Py_ValidIndex(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; } @@ -1613,7 +1613,7 @@ bytes_subscript(PyBytesObject* self, PyObject* item) return NULL; if (i < 0) i += PyBytes_GET_SIZE(self); - if (i < 0 || i >= PyBytes_GET_SIZE(self)) { + if (!_Py_ValidIndex(i, PyBytes_GET_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; @@ -2810,7 +2810,7 @@ _PyBytes_FromList(PyObject *x) if (value == -1 && PyErr_Occurred()) goto error; - if (value < 0 || value >= 256) { + if (!_Py_ValidIndex(value, 256)) { PyErr_SetString(PyExc_ValueError, "bytes must be in range(0, 256)"); goto error; @@ -2851,7 +2851,7 @@ _PyBytes_FromTuple(PyObject *x) if (value == -1 && PyErr_Occurred()) goto error; - if (value < 0 || value >= 256) { + if (!_Py_ValidIndex(value, 256)) { PyErr_SetString(PyExc_ValueError, "bytes must be in range(0, 256)"); goto error; @@ -2904,7 +2904,7 @@ _PyBytes_FromIterator(PyObject *it, PyObject *x) goto error; /* Range check */ - if (value < 0 || value >= 256) { + if (!_Py_ValidIndex(value, 256)) { PyErr_SetString(PyExc_ValueError, "bytes must be in range(0, 256)"); goto error; @@ -3662,4 +3662,3 @@ _PyBytes_Repeat(char* dest, Py_ssize_t len_dest, } } } - diff --git a/Objects/dictobject.c b/Objects/dictobject.c index a1ee32b7099f91..beb963f122aa8b 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -116,6 +116,7 @@ As a consequence of this, split keys have a maximum size of 16. #define PyDict_MINSIZE 8 #include "Python.h" +#include "pycore_abstract.h" // _Py_ValidIndex() #include "pycore_bitutils.h" // _Py_bit_length #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_GetBuiltin() @@ -2814,7 +2815,7 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, i = *ppos; if (_PyDict_HasSplitTable(mp)) { assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE); - if (i < 0 || i >= mp->ma_used) + if (!_Py_ValidIndex(i, mp->ma_used)) return 0; int index = get_index_from_order(mp, i); value = mp->ma_values->values[index]; @@ -2824,7 +2825,7 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, } else { Py_ssize_t n = mp->ma_keys->dk_nentries; - if (i < 0 || i >= n) + if (!_Py_ValidIndex(i, n)) return 0; if (DK_IS_UNICODE(mp->ma_keys)) { PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(mp->ma_keys)[i]; diff --git a/Objects/listobject.c b/Objects/listobject.c index d09bb6391034d1..5e536893c013ad 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1,7 +1,7 @@ /* List object implementation */ #include "Python.h" -#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_abstract.h" // _PyIndex_Check(), _Py_ValidIndex() #include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_dict.h" // _PyDictViewObject #include "pycore_pyatomic_ft_wrappers.h" @@ -324,19 +324,6 @@ PyList_Size(PyObject *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; -} - #ifdef Py_GIL_DISABLED static PyObject * @@ -348,7 +335,7 @@ list_item_impl(PyListObject *self, Py_ssize_t idx) _PyObject_GC_SET_SHARED(self); } Py_ssize_t size = Py_SIZE(self); - if (!valid_index(idx, size)) { + if (!_Py_ValidIndex(idx, size)) { goto exit; } #ifdef Py_GIL_DISABLED @@ -369,7 +356,7 @@ list_get_item_ref(PyListObject *op, Py_ssize_t i) } // Need atomic operation for the getting size. Py_ssize_t size = PyList_GET_SIZE(op); - if (!valid_index(i, size)) { + if (!_Py_ValidIndex(i, size)) { return NULL; } PyObject **ob_item = _Py_atomic_load_ptr(&op->ob_item); @@ -378,7 +365,7 @@ list_get_item_ref(PyListObject *op, Py_ssize_t i) } Py_ssize_t cap = list_capacity(ob_item); assert(cap != -1 && cap >= size); - if (!valid_index(i, cap)) { + if (!_Py_ValidIndex(i, cap)) { return NULL; } PyObject *item = _Py_TryXGetRef(&ob_item[i]); @@ -391,7 +378,7 @@ list_get_item_ref(PyListObject *op, Py_ssize_t i) static inline PyObject* list_get_item_ref(PyListObject *op, Py_ssize_t i) { - if (!valid_index(i, Py_SIZE(op))) { + if (!_Py_ValidIndex(i, Py_SIZE(op))) { return NULL; } return Py_NewRef(PyList_GET_ITEM(op, i)); @@ -405,7 +392,7 @@ PyList_GetItem(PyObject *op, Py_ssize_t i) PyErr_BadInternalCall(); return NULL; } - if (!valid_index(i, Py_SIZE(op))) { + if (!_Py_ValidIndex(i, Py_SIZE(op))) { _Py_DECLARE_STR(list_err, "list index out of range"); PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err)); return NULL; @@ -442,7 +429,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i, int ret; PyListObject *self = ((PyListObject *)op); Py_BEGIN_CRITICAL_SECTION(self); - if (!valid_index(i, Py_SIZE(self))) { + if (!_Py_ValidIndex(i, Py_SIZE(self))) { Py_XDECREF(newitem); PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); @@ -655,7 +642,7 @@ static PyObject * list_item(PyObject *aa, Py_ssize_t i) { PyListObject *a = (PyListObject *)aa; - if (!valid_index(i, PyList_GET_SIZE(a))) { + if (!_Py_ValidIndex(i, PyList_GET_SIZE(a))) { PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err)); return NULL; } @@ -1056,7 +1043,7 @@ list_inplace_repeat(PyObject *_self, Py_ssize_t n) static int list_ass_item_lock_held(PyListObject *a, Py_ssize_t i, PyObject *v) { - if (!valid_index(i, Py_SIZE(a))) { + if (!_Py_ValidIndex(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); return -1; @@ -1497,7 +1484,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) } if (index < 0) index += Py_SIZE(self); - if (!valid_index(index, Py_SIZE(self))) { + if (!_Py_ValidIndex(index, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 5caa6504272301..46dd8e876b05cc 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -11,7 +11,7 @@ */ #include "Python.h" -#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_abstract.h" // _PyIndex_Check(), _Py_ValidIndex() #include "pycore_memoryobject.h" // _PyManagedBuffer_Type #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_strhex.h" // _Py_strhex_with_sep() @@ -2378,7 +2378,7 @@ lookup_dimension(const Py_buffer *view, char *ptr, int dim, Py_ssize_t index) if (index < 0) { index += nitems; } - if (index < 0 || index >= nitems) { + if (!_Py_ValidIndex(index, nitems)) { PyErr_Format(PyExc_IndexError, "index out of bounds on dimension %d", dim + 1); return NULL; diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 5ae1ee9a89af84..630bc4aba0e313 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -2,7 +2,7 @@ /* Tuple object implementation */ #include "Python.h" -#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_abstract.h" // _PyIndex_Check(), _Py_ValidIndex() #include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() #include "pycore_initconfig.h" // _PyStatus_OK() @@ -102,7 +102,7 @@ PyTuple_GetItem(PyObject *op, Py_ssize_t i) PyErr_BadInternalCall(); return NULL; } - if (i < 0 || i >= Py_SIZE(op)) { + if (!_Py_ValidIndex(i, Py_SIZE(op))) { PyErr_SetString(PyExc_IndexError, "tuple index out of range"); return NULL; } @@ -118,7 +118,7 @@ PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem) PyErr_BadInternalCall(); return -1; } - if (i < 0 || i >= Py_SIZE(op)) { + if (!_Py_ValidIndex(i, Py_SIZE(op))) { Py_XDECREF(newitem); PyErr_SetString(PyExc_IndexError, "tuple assignment index out of range"); @@ -363,7 +363,7 @@ tuplecontains(PyTupleObject *a, PyObject *el) static PyObject * tupleitem(PyTupleObject *a, Py_ssize_t i) { - if (i < 0 || i >= Py_SIZE(a)) { + if (!_Py_ValidIndex(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "tuple index out of range"); return NULL; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 3b0b4173408724..66b5f8dc3b1a34 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -39,7 +39,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "Python.h" -#include "pycore_abstract.h" // _PyIndex_Check() +#include "pycore_abstract.h" // _PyIndex_Check(), _Py_ValidIndex() #include "pycore_bytes_methods.h" // _Py_bytes_lower() #include "pycore_bytesobject.h" // _PyBytes_Repeat() #include "pycore_ceval.h" // _PyEval_GetBuiltin() @@ -3970,7 +3970,7 @@ PyUnicode_ReadChar(PyObject *unicode, Py_ssize_t index) PyErr_BadArgument(); return (Py_UCS4)-1; } - if (index < 0 || index >= PyUnicode_GET_LENGTH(unicode)) { + if (!_Py_ValidIndex(index, PyUnicode_GET_LENGTH(unicode))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return (Py_UCS4)-1; } @@ -3986,7 +3986,7 @@ PyUnicode_WriteChar(PyObject *unicode, Py_ssize_t index, Py_UCS4 ch) PyErr_BadArgument(); return -1; } - if (index < 0 || index >= PyUnicode_GET_LENGTH(unicode)) { + if (!_Py_ValidIndex(index, PyUnicode_GET_LENGTH(unicode))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return -1; } @@ -11368,7 +11368,7 @@ unicode_getitem(PyObject *self, Py_ssize_t index) PyErr_BadArgument(); return NULL; } - if (index < 0 || index >= PyUnicode_GET_LENGTH(self)) { + if (!_Py_ValidIndex(index, PyUnicode_GET_LENGTH(self))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return NULL; } diff --git a/Python/optimizer.c b/Python/optimizer.c index 4dc3438b6c23a4..cfc648f91ca395 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -3,6 +3,7 @@ #include "Python.h" #include "opcode.h" #include "pycore_interp.h" +#include "pycore_abstract.h" // _Py_ValidIndex() #include "pycore_backoff.h" #include "pycore_bitutils.h" // _Py_popcount32() #include "pycore_object.h" // _PyObject_GC_UNTRACK() @@ -357,7 +358,7 @@ static PyObject * uop_item(_PyExecutorObject *self, Py_ssize_t index) { Py_ssize_t len = uop_len(self); - if (index < 0 || index >= len) { + if (!_Py_ValidIndex(index, len)) { PyErr_SetNone(PyExc_IndexError); return NULL; }