@@ -208,6 +208,19 @@ PyList_Size(PyObject *op)
208
208
return Py_SIZE (op );
209
209
}
210
210
211
+ static inline int
212
+ valid_index (Py_ssize_t i , Py_ssize_t limit )
213
+ {
214
+ /* The cast to size_t lets us use just a single comparison
215
+ to check whether i is in the range: 0 <= i < limit.
216
+
217
+ See: Section 14.2 "Bounds Checking" in the Agner Fog
218
+ optimization manual found at:
219
+ https://www.agner.org/optimize/optimizing_cpp.pdf
220
+ */
221
+ return (size_t ) i < (size_t ) limit ;
222
+ }
223
+
211
224
static PyObject * indexerr = NULL ;
212
225
213
226
PyObject *
@@ -217,7 +230,7 @@ PyList_GetItem(PyObject *op, Py_ssize_t i)
217
230
PyErr_BadInternalCall ();
218
231
return NULL ;
219
232
}
220
- if (i < 0 || i >= Py_SIZE (op )) {
233
+ if (! valid_index ( i , Py_SIZE (op ) )) {
221
234
if (indexerr == NULL ) {
222
235
indexerr = PyUnicode_FromString (
223
236
"list index out of range" );
@@ -240,7 +253,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i,
240
253
PyErr_BadInternalCall ();
241
254
return -1 ;
242
255
}
243
- if (i < 0 || i >= Py_SIZE (op )) {
256
+ if (! valid_index ( i , Py_SIZE (op ) )) {
244
257
Py_XDECREF (newitem );
245
258
PyErr_SetString (PyExc_IndexError ,
246
259
"list assignment index out of range" );
@@ -426,7 +439,7 @@ list_contains(PyListObject *a, PyObject *el)
426
439
static PyObject *
427
440
list_item (PyListObject * a , Py_ssize_t i )
428
441
{
429
- if (i < 0 || i >= Py_SIZE (a )) {
442
+ if (! valid_index ( i , Py_SIZE (a ) )) {
430
443
if (indexerr == NULL ) {
431
444
indexerr = PyUnicode_FromString (
432
445
"list index out of range" );
@@ -749,7 +762,7 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n)
749
762
static int
750
763
list_ass_item (PyListObject * a , Py_ssize_t i , PyObject * v )
751
764
{
752
- if (i < 0 || i >= Py_SIZE (a )) {
765
+ if (! valid_index ( i , Py_SIZE (a ) )) {
753
766
PyErr_SetString (PyExc_IndexError ,
754
767
"list assignment index out of range" );
755
768
return -1 ;
@@ -996,7 +1009,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index)
996
1009
}
997
1010
if (index < 0 )
998
1011
index += Py_SIZE (self );
999
- if (index < 0 || index >= Py_SIZE (self )) {
1012
+ if (! valid_index ( index , Py_SIZE (self ) )) {
1000
1013
PyErr_SetString (PyExc_IndexError , "pop index out of range" );
1001
1014
return NULL ;
1002
1015
}
0 commit comments