Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-99761: add invalid_index macro #99762

Closed
wants to merge 52 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
0d1b08a
add invalid_index
eendebakpt Nov 24, 2022
be6143f
replace valid_index
eendebakpt Nov 25, 2022
bcaec88
📜🤖 Added by blurb_it.
blurb-it[bot] Nov 25, 2022
6dd6fec
make regen-all
eendebakpt Nov 25, 2022
7a35197
Merge branch 'list_tuple' of github.com:eendebakpt/cpython into list_…
eendebakpt Nov 25, 2022
1e4448f
Rename 2022-11-25-09-34-57.gh-issue-9761.sRqH37.rst to 2022-11-25-09-…
eendebakpt Nov 25, 2022
1d58ef0
add method for int check
eendebakpt Nov 25, 2022
76ecde6
change invalid_index to valid_index
eendebakpt Nov 26, 2022
c356130
change invalid_index to valid_index
eendebakpt Nov 26, 2022
329d6ed
revert changes to _collectionsmodule.c on request of the author
eendebakpt Nov 26, 2022
bbdb3b5
make valid_index private
eendebakpt Nov 26, 2022
45d4abf
change static inline to macro
eendebakpt Nov 26, 2022
e78d129
typo
eendebakpt Nov 26, 2022
5cc1dfc
unto changes to _collectionsmodule.c
eendebakpt Nov 26, 2022
a112a05
Merge branch 'main' into list_tuple
eendebakpt Nov 26, 2022
d04aa18
rename to static inline int _Py_is_valid_index
eendebakpt Nov 28, 2022
d6c614c
update news item
eendebakpt Nov 28, 2022
77e8cc4
double backticks
eendebakpt Nov 28, 2022
90fa51f
Merge branch 'main' into list_tuple
eendebakpt Nov 28, 2022
6e334bc
fix docstring
eendebakpt Nov 29, 2022
242de2d
Merge branch 'list_tuple' of githubeendebakpt:eendebakpt/cpython into…
eendebakpt Nov 29, 2022
fe8b462
Update Include/internal/pycore_abstract.h
eendebakpt Dec 6, 2022
901dd4c
revert changes with _PyLong_negative_or_multi_digit_int
eendebakpt Dec 6, 2022
3fbbaae
update documentation
eendebakpt Dec 6, 2022
366f2ec
revert changes in bytecodes.c
eendebakpt Dec 7, 2022
7795929
Update Include/internal/pycore_abstract.h
vstinner Dec 8, 2022
87f65e6
Update Include/internal/pycore_abstract.h
vstinner Dec 8, 2022
f7b22bf
Update Objects/codeobject.c
vstinner Dec 8, 2022
1e47517
Update Modules/mmapmodule.c
vstinner Dec 8, 2022
e510943
Update Modules/arraymodule.c
vstinner Dec 8, 2022
61bd3a4
remove news entry
eendebakpt Dec 10, 2022
6f0e26e
remove comment about twos-complement
eendebakpt Dec 10, 2022
ae35168
Merge branch 'main' into list_tuple
eendebakpt Dec 10, 2022
1c86e98
Merge branch 'main' into list_tuple
eendebakpt Dec 21, 2022
8633a20
Merge branch 'main' into list_tuple
eendebakpt Dec 26, 2022
55e6d70
Merge branch 'main' into list_tuple
eendebakpt Jan 18, 2023
4185f3c
Merge branch 'main' into list_tuple
eendebakpt Jan 26, 2023
24f0aa0
Merge branch 'main' into list_tuple
eendebakpt Feb 5, 2023
8c1332a
Merge branch 'main' into list_tuple
eendebakpt Feb 16, 2023
8ca17f7
Merge branch 'main' into list_tuple
eendebakpt Feb 20, 2023
4377b07
review comments
eendebakpt Feb 20, 2023
2e871e9
Merge branch 'main' into list_tuple
eendebakpt Feb 20, 2023
4699151
Merge branch 'main' into list_tuple
eendebakpt Mar 19, 2023
795bf2d
Merge branch 'main' into list_tuple
eendebakpt Apr 4, 2023
3ca5d8b
Merge branch 'main' into list_tuple
eendebakpt Apr 28, 2023
fe17e85
Merge branch 'main' into list_tuple
eendebakpt May 20, 2023
7cb70fc
Merge branch 'main' into list_tuple
eendebakpt Jun 21, 2023
a072101
Merge branch 'main' into list_tuple
eendebakpt Jun 28, 2023
7204d8a
Merge branch 'main' into list_tuple
eendebakpt Jul 18, 2023
977e7cc
Merge branch 'main' into list_tuple
eendebakpt Sep 25, 2023
d3b633e
Merge branch 'main' into list_tuple
eendebakpt Nov 16, 2023
cad941a
Merge branch 'main' into list_tuple
eendebakpt Dec 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Include/internal/pycore_abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif

/* Return 1 if the specified index is outside the range[0, limit) */
#define valid_index(index, limit) ((size_t)index < (size_t)limit)
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
/* The cast to size_t lets us use just a single comparison
to check whether index is in the range: 0 <= index < limit.

See: Section 14.2 "Bounds Checking" in the Agner Fog
optimization manual found at:
https://www.agner.org/optimize/optimizing_cpp.pdf
*/

// Fast inlined version of PyIndex_Check()
static inline int
_PyIndex_Check(PyObject *obj)
Expand Down
4 changes: 4 additions & 0 deletions Include/internal/pycore_long.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
return Py_NewRef((PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i]);
}

/* Return 1 if the argument is negative or a multi-digit int */
#define _PyLong_Negative_or_multi_digit_int(sub) (assert(PyLong_CheckExact(sub)), \
((size_t)Py_SIZE(sub)) > 1)

PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add method to calculate invalid_index
9 changes: 5 additions & 4 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_abstract.h" // valid_index
vstinner marked this conversation as resolved.
Show resolved Hide resolved
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_bytesobject.h" // _PyBytes_Repeat
#include "structmember.h" // PyMemberDef
Expand Down Expand Up @@ -804,7 +805,7 @@ array_length(arrayobject *a)
static PyObject *
array_item(arrayobject *a, Py_ssize_t i)
{
if (i < 0 || i >= Py_SIZE(a)) {
if (!valid_index(i, Py_SIZE(a))) {
PyErr_SetString(PyExc_IndexError, "array index out of range");
return NULL;
}
Expand Down Expand Up @@ -966,7 +967,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 (!valid_index(i, Py_SIZE(a))) {
PyErr_SetString(PyExc_IndexError,
"array assignment index out of range");
return -1;
Expand Down Expand Up @@ -1249,7 +1250,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 (!valid_index(i, Py_SIZE(self))) {
PyErr_SetString(PyExc_IndexError, "pop index out of range");
return NULL;
}
Expand Down Expand Up @@ -2407,7 +2408,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 (!valid_index(i, Py_SIZE(self))) {
PyErr_SetString(PyExc_IndexError,
"array assignment index out of range");
return -1;
Expand Down
9 changes: 5 additions & 4 deletions Modules/mmapmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "pycore_abstract.h" // valid_index
vstinner marked this conversation as resolved.
Show resolved Hide resolved
#include "pycore_bytesobject.h" // _PyBytes_Find()
#include "pycore_fileutils.h" // _Py_stat_struct
#include "structmember.h" // PyMemberDef
Expand Down Expand Up @@ -920,7 +921,7 @@ static PyObject *
mmap_item(mmap_object *self, Py_ssize_t i)
{
CHECK_VALID(NULL);
if (i < 0 || i >= self->size) {
if (!valid_index(i, self->size)) {
PyErr_SetString(PyExc_IndexError, "mmap index out of range");
return NULL;
}
Expand All @@ -937,7 +938,7 @@ mmap_subscript(mmap_object *self, PyObject *item)
return NULL;
if (i < 0)
i += self->size;
if (i < 0 || i >= self->size) {
if (!valid_index(i, self->size)) {
PyErr_SetString(PyExc_IndexError,
"mmap index out of range");
return NULL;
Expand Down Expand Up @@ -988,7 +989,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 (!valid_index(i, self->size)) {
PyErr_SetString(PyExc_IndexError, "mmap index out of range");
return -1;
}
Expand Down Expand Up @@ -1025,7 +1026,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 (!valid_index(i, self->size)) {
PyErr_SetString(PyExc_IndexError,
"mmap index out of range");
return -1;
Expand Down
10 changes: 5 additions & 5 deletions Objects/bytearrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,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 (!valid_index(i, Py_SIZE(self))) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return NULL;
}
Expand All @@ -377,7 +377,7 @@ bytearray_subscript(PyByteArrayObject *self, PyObject *index)
if (i < 0)
i += PyByteArray_GET_SIZE(self);

if (i < 0 || i >= Py_SIZE(self)) {
if (!valid_index(i, Py_SIZE(self))) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return NULL;
}
Expand Down Expand Up @@ -572,7 +572,7 @@ bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value)
i += Py_SIZE(self);
}

if (i < 0 || i >= Py_SIZE(self)) {
if (!valid_index(i, Py_SIZE(self))) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return -1;
}
Expand Down Expand Up @@ -612,7 +612,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu
i += PyByteArray_GET_SIZE(self);
}

if (i < 0 || i >= Py_SIZE(self)) {
if (!valid_index(i, Py_SIZE(self))) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return -1;
}
Expand Down Expand Up @@ -1809,7 +1809,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 (!valid_index(index, Py_SIZE(self))) {
PyErr_SetString(PyExc_IndexError, "pop index out of range");
return NULL;
}
Expand Down
4 changes: 2 additions & 2 deletions Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1484,7 +1484,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 (!valid_index(i, Py_SIZE(a))) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return NULL;
}
Expand Down Expand Up @@ -1591,7 +1591,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 (!valid_index(i, PyBytes_GET_SIZE(self))) {
PyErr_SetString(PyExc_IndexError,
"index out of range");
return NULL;
Expand Down
4 changes: 2 additions & 2 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Python.h"
#include "opcode.h"
#include "structmember.h" // PyMemberDef
#include "pycore_abstract.h" // valid_index
vstinner marked this conversation as resolved.
Show resolved Hide resolved
#include "pycore_code.h" // _PyCodeConstructor
#include "pycore_frame.h" // FRAME_SPECIALS_SIZE
#include "pycore_interp.h" // PyInterpreterState.co_extra_freefuncs
Expand Down Expand Up @@ -1346,8 +1347,7 @@ _PyCode_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) || !valid_index(index, interp->co_extra_user_count)) {
PyErr_BadInternalCall();
return -1;
}
Expand Down
15 changes: 1 addition & 14 deletions Objects/listobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,18 +226,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)
Expand Down Expand Up @@ -2584,9 +2572,8 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start,
}
if (stop < 0) {
stop += Py_SIZE(self);
if (stop < 0)
stop = 0;
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
}

for (i = start; i < stop && i < Py_SIZE(self); i++) {
PyObject *obj = self->ob_item[i];
Py_INCREF(obj);
Expand Down
2 changes: 1 addition & 1 deletion Objects/memoryobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2299,7 +2299,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 (!valid_index(index, nitems)) {
PyErr_Format(PyExc_IndexError,
"index out of bounds on dimension %d", dim + 1);
return NULL;
Expand Down
6 changes: 3 additions & 3 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ PyTuple_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))) {
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
return NULL;
}
Expand All @@ -116,7 +116,7 @@ PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
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,
"tuple assignment index out of range");
Expand Down Expand Up @@ -361,7 +361,7 @@ tuplecontains(PyTupleObject *a, PyObject *el)
static PyObject *
tupleitem(PyTupleObject *a, Py_ssize_t i)
{
if (i < 0 || i >= Py_SIZE(a)) {
if (!valid_index(i, Py_SIZE(a))) {
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
return NULL;
}
Expand Down
6 changes: 3 additions & 3 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1436,11 +1436,11 @@ PyUnicode_CopyCharacters(PyObject *to, Py_ssize_t to_start,
return -1;
}

if ((size_t)from_start > (size_t)PyUnicode_GET_LENGTH(from)) {
if (!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 (!valid_index(to_start, PyUnicode_GET_LENGTH(to))) {
PyErr_SetString(PyExc_IndexError, "string index out of range");
return -1;
}
Expand Down Expand Up @@ -3721,7 +3721,7 @@ PyUnicode_ReadChar(PyObject *unicode, Py_ssize_t index)
PyErr_BadArgument();
return (Py_UCS4)-1;
}
if (index < 0 || index >= PyUnicode_GET_LENGTH(unicode)) {
if (!valid_index(index, PyUnicode_GET_LENGTH(unicode))) {
PyErr_SetString(PyExc_IndexError, "string index out of range");
return (Py_UCS4)-1;
}
Expand Down
8 changes: 3 additions & 5 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,7 @@ dummy_func(
DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);

// Deopt unless 0 <= sub < PyList_Size(list)
Py_ssize_t signed_magnitude = Py_SIZE(sub);
DEOPT_IF(((size_t)signed_magnitude) > 1, BINARY_SUBSCR);
DEOPT_IF(_PyLong_Negative_or_multi_digit_int(sub), BINARY_SUBSCR);
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
assert(((PyLongObject *)_PyLong_GetZero())->ob_digit[0] == 0);
Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);
Expand All @@ -402,8 +401,7 @@ dummy_func(
DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);

// Deopt unless 0 <= sub < PyTuple_Size(list)
Py_ssize_t signed_magnitude = Py_SIZE(sub);
DEOPT_IF(((size_t)signed_magnitude) > 1, BINARY_SUBSCR);
DEOPT_IF(_PyLong_Negative_or_multi_digit_int(sub), BINARY_SUBSCR);
assert(((PyLongObject *)_PyLong_GetZero())->ob_digit[0] == 0);
Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);
Expand Down Expand Up @@ -507,7 +505,7 @@ dummy_func(
DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);

// Ensure nonnegative, zero-or-one-digit ints.
DEOPT_IF(((size_t)Py_SIZE(sub)) > 1, STORE_SUBSCR);
DEOPT_IF(_PyLong_Negative_or_multi_digit_int(sub), STORE_SUBSCR);
Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
// Ensure index < len(list)
DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR);
Expand Down
8 changes: 3 additions & 5 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.