diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h index 3cc0afac4bd5b4..0d2c2bb9242c19 100644 --- a/Include/internal/pycore_abstract.h +++ b/Include/internal/pycore_abstract.h @@ -8,6 +8,23 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +// Return 1 if 0 <= index < limit and 0 otherwise +// The argument limit should be non-negative +static inline int _Py_is_valid_index(Py_ssize_t index, 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 + + The function is not affected by -fwrapv, -fno-wrapv and -ftrapv + compiler options of GCC and clang + */ + assert(limit >= 0); + return (size_t)index < (size_t)limit; +} + // Fast inlined version of PyIndex_Check() static inline int _PyIndex_Check(PyObject *obj) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index b97ade6126fa08..20ccfe19114821 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -8,6 +8,7 @@ #endif #include "Python.h" +#include "pycore_abstract.h" // _Py_is_valid_index() #include "pycore_bytesobject.h" // _PyBytes_Repeat #include "pycore_call.h" // _PyObject_CallMethod() #include "pycore_ceval.h" // _PyEval_GetBuiltin() @@ -835,7 +836,7 @@ array_length(arrayobject *a) static PyObject * array_item(arrayobject *a, Py_ssize_t i) { - if (i < 0 || i >= Py_SIZE(a)) { + if (!_Py_is_valid_index(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "array index out of range"); return NULL; } @@ -997,7 +998,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_is_valid_index(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); return -1; @@ -1280,7 +1281,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_is_valid_index(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } @@ -2470,7 +2471,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_is_valid_index(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 66ed0b8efb775c..34e375cfb82049 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_is_valid_index(), _Py_convert_optional_to_ssize_t() #include "pycore_bytesobject.h" // _PyBytes_Find() #include "pycore_fileutils.h" // _Py_stat_struct @@ -960,7 +960,7 @@ static PyObject * mmap_item(mmap_object *self, Py_ssize_t i) { CHECK_VALID(NULL); - if (i < 0 || i >= self->size) { + if (!_Py_is_valid_index(i, self->size)) { PyErr_SetString(PyExc_IndexError, "mmap index out of range"); return NULL; } @@ -977,7 +977,7 @@ mmap_subscript(mmap_object *self, PyObject *item) return NULL; if (i < 0) i += self->size; - if (i < 0 || i >= self->size) { + if (!_Py_is_valid_index(i, self->size)) { PyErr_SetString(PyExc_IndexError, "mmap index out of range"); return NULL; @@ -1031,7 +1031,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_is_valid_index(i, self->size)) { PyErr_SetString(PyExc_IndexError, "mmap index out of range"); return -1; } @@ -1068,7 +1068,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_is_valid_index(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 659de7d3dd5a99..2d51c18a55e2c1 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -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_is_valid_index(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_is_valid_index(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_is_valid_index(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_is_valid_index(i, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return -1; } @@ -1810,7 +1810,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_is_valid_index(index, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 26227dd251122d..75ea9025c78c73 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1495,7 +1495,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_is_valid_index(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; } @@ -1602,7 +1602,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_is_valid_index(i, PyBytes_GET_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; diff --git a/Objects/codeobject.c b/Objects/codeobject.c index dc46b773c26528..05f87c64e3a90c 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -2,7 +2,8 @@ #include "Python.h" #include "opcode.h" - +#include "structmember.h" // PyMemberDef +#include "pycore_abstract.h" // _Py_is_valid_index() #include "pycore_code.h" // _PyCodeConstructor #include "pycore_frame.h" // FRAME_SPECIALS_SIZE #include "pycore_interp.h" // PyInterpreterState.co_extra_freefuncs @@ -1382,8 +1383,7 @@ PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra) { PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!PyCode_Check(code) || index < 0 || - index >= interp->co_extra_user_count) { + if (!PyCode_Check(code) || !_Py_is_valid_index(index, interp->co_extra_user_count)) { PyErr_BadInternalCall(); return -1; } diff --git a/Objects/listobject.c b/Objects/listobject.c index 2d04218439bd20..e1e3d5de77fcf6 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -229,18 +229,6 @@ 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; -} PyObject * PyList_GetItem(PyObject *op, Py_ssize_t i) @@ -249,7 +237,7 @@ PyList_GetItem(PyObject *op, Py_ssize_t i) PyErr_BadInternalCall(); return NULL; } - if (!valid_index(i, Py_SIZE(op))) { + if (!_Py_is_valid_index(i, Py_SIZE(op))) { _Py_DECLARE_STR(list_err, "list index out of range"); PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err)); return NULL; @@ -267,7 +255,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i, PyErr_BadInternalCall(); return -1; } - if (!valid_index(i, Py_SIZE(op))) { + if (!_Py_is_valid_index(i, Py_SIZE(op))) { Py_XDECREF(newitem); PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); @@ -458,7 +446,7 @@ list_contains(PyListObject *a, PyObject *el) static PyObject * list_item(PyListObject *a, Py_ssize_t i) { - if (!valid_index(i, Py_SIZE(a))) { + if (!_Py_is_valid_index(i, Py_SIZE(a))) { PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err)); return NULL; } @@ -778,7 +766,7 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n) static int list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v) { - if (!valid_index(i, Py_SIZE(a))) { + if (!_Py_is_valid_index(i, Py_SIZE(a))) { PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); return -1; @@ -1077,7 +1065,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_is_valid_index(index, Py_SIZE(self))) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } @@ -2670,9 +2658,8 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start, } if (stop < 0) { stop += Py_SIZE(self); - if (stop < 0) - stop = 0; } + for (i = start; i < stop && i < Py_SIZE(self); i++) { PyObject *obj = self->ob_item[i]; Py_INCREF(obj); diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 6a38952fdc1f3b..5e07d0d235ed2b 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -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_is_valid_index(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 d567839c5e3a0b..cb5eee3526442f 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -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_is_valid_index(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_is_valid_index(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_is_valid_index(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 836e14fd5d5dea..54672c603be06c 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1487,11 +1487,11 @@ PyUnicode_CopyCharacters(PyObject *to, Py_ssize_t to_start, return -1; } - if ((size_t)from_start > (size_t)PyUnicode_GET_LENGTH(from)) { + if (!_Py_is_valid_index(from_start, PyUnicode_GET_LENGTH(from))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return -1; } - if ((size_t)to_start > (size_t)PyUnicode_GET_LENGTH(to)) { + if (!_Py_is_valid_index(to_start, PyUnicode_GET_LENGTH(to))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return -1; } @@ -3895,7 +3895,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_is_valid_index(index, PyUnicode_GET_LENGTH(unicode))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return (Py_UCS4)-1; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy