Macro form of :c:func:`PyList_SetItem` without error checking. This is
normally only used to fill in new lists where there is no previous content.
+ Bounds checking is performed as an assertion if Python is built in
+ :ref:`debug mode <debug-build>` or :option:`with assertions
+ <--with-assertions>`.
+
.. note::
This macro "steals" a reference to *item*, and, unlike
Like :c:func:`PyTuple_SetItem`, but does no error checking, and should *only* be
used to fill in brand new tuples.
+ Bounds checking is performed as an assertion if Python is built in
+ :ref:`debug mode <debug-build>` or :option:`with assertions <--with-assertions>`.
+
.. note::
This function "steals" a reference to *o*, and, unlike
.. c:function:: PyObject* PyStructSequence_GetItem(PyObject *p, Py_ssize_t pos)
Return the object at position *pos* in the struct sequence pointed to by *p*.
- No bounds checking is performed.
+
+ Bounds checking is performed as an assertion if Python is built in
+ :ref:`debug mode <debug-build>` or :option:`with assertions <--with-assertions>`.
.. c:function:: PyObject* PyStructSequence_GET_ITEM(PyObject *p, Py_ssize_t pos)
- Macro equivalent of :c:func:`PyStructSequence_GetItem`.
+ Alias to :c:func:`PyStructSequence_GetItem`.
+
+ .. versionchanged:: 3.13
+ Now implemented as an alias to :c:func:`PyStructSequence_GetItem`.
.. c:function:: void PyStructSequence_SetItem(PyObject *p, Py_ssize_t pos, PyObject *o)
:c:func:`PyTuple_SET_ITEM`, this should only be used to fill in brand new
instances.
+ Bounds checking is performed as an assertion if Python is built in
+ :ref:`debug mode <debug-build>` or :option:`with assertions <--with-assertions>`.
+
.. note::
This function "steals" a reference to *o*.
.. c:function:: void PyStructSequence_SET_ITEM(PyObject *p, Py_ssize_t *pos, PyObject *o)
- Similar to :c:func:`PyStructSequence_SetItem`, but implemented as a static
- inlined function.
+ Alias to :c:func:`PyStructSequence_SetItem`.
- .. note::
-
- This function "steals" a reference to *o*.
+ .. versionchanged:: 3.13
+ Now implemented as an alias to :c:func:`PyStructSequence_SetItem`.
``NULL`` if the referent is no longer live.
(Contributed by Victor Stinner in :gh:`105927`.)
+* If Python is built in :ref:`debug mode <debug-build>` or :option:`with
+ assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and
+ :c:func:`PyList_SET_ITEM` now check the index argument with an assertion.
+ If the assertion fails, make sure that the size is set before.
+ (Contributed by Victor Stinner in :gh:`106168`.)
+
Porting to Python 3.13
----------------------
static inline void
PyList_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) {
PyListObject *list = _PyList_CAST(op);
+ assert(0 <= index);
+ assert(index < Py_SIZE(list));
list->ob_item[index] = value;
}
#define PyList_SET_ITEM(op, index, value) \
static inline void
PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) {
PyTupleObject *tuple = _PyTuple_CAST(op);
+ assert(0 <= index);
+ assert(index < Py_SIZE(tuple));
tuple->ob_item[index] = value;
}
#define PyTuple_SET_ITEM(op, index, value) \
Py_ssize_t allocated = self->allocated;
assert((size_t)len + 1 < PY_SSIZE_T_MAX);
if (allocated > len) {
- PyList_SET_ITEM(self, len, newitem);
Py_SET_SIZE(self, len + 1);
+ PyList_SET_ITEM(self, len, newitem);
return 0;
}
return _PyList_AppendTakeRefListResize(self, newitem);
PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type);
+PyAPI_FUNC(void) PyStructSequence_SetItem(PyObject*, Py_ssize_t, PyObject*);
+PyAPI_FUNC(PyObject*) PyStructSequence_GetItem(PyObject*, Py_ssize_t);
+
#ifndef Py_LIMITED_API
typedef PyTupleObject PyStructSequence;
-
-/* Macro, *only* to be used to fill in brand new objects */
-#define PyStructSequence_SET_ITEM(op, i, v) PyTuple_SET_ITEM((op), (i), (v))
-
-#define PyStructSequence_GET_ITEM(op, i) PyTuple_GET_ITEM((op), (i))
+#define PyStructSequence_SET_ITEM PyStructSequence_SetItem
+#define PyStructSequence_GET_ITEM PyStructSequence_GetItem
#endif
-PyAPI_FUNC(void) PyStructSequence_SetItem(PyObject*, Py_ssize_t, PyObject*);
-PyAPI_FUNC(PyObject*) PyStructSequence_GetItem(PyObject*, Py_ssize_t);
-
#ifdef __cplusplus
}
#endif
--- /dev/null
+If Python is built in :ref:`debug mode <debug-build>` or :option:`with
+assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and
+:c:func:`PyList_SET_ITEM` now check the index argument with an assertion. If
+the assertion fails, make sure that the size is set before. Patch by Victor
+Stinner.
}
if (Py_SIZE(self) < self->allocated) {
/* steals ref */
- PyList_SET_ITEM(self, Py_SIZE(self), item);
- Py_SET_SIZE(self, Py_SIZE(self) + 1);
+ Py_ssize_t len = Py_SIZE(self);
+ Py_SET_SIZE(self, len + 1);
+ PyList_SET_ITEM(self, len, item);
}
else {
if (_PyList_AppendTakeRef(self, item) < 0)
}
void
-PyStructSequence_SetItem(PyObject* op, Py_ssize_t i, PyObject* v)
+PyStructSequence_SetItem(PyObject *op, Py_ssize_t index, PyObject *value)
{
- PyStructSequence_SET_ITEM(op, i, v);
+ PyTupleObject *tuple = _PyTuple_CAST(op);
+ assert(0 <= index);
+#ifndef NDEBUG
+ Py_ssize_t n_fields = REAL_SIZE(op);
+ assert(n_fields >= 0);
+ assert(index < n_fields);
+#endif
+ tuple->ob_item[index] = value;
}
PyObject*
-PyStructSequence_GetItem(PyObject* op, Py_ssize_t i)
+PyStructSequence_GetItem(PyObject *op, Py_ssize_t index)
{
- return PyStructSequence_GET_ITEM(op, i);
+ assert(0 <= index);
+#ifndef NDEBUG
+ Py_ssize_t n_fields = REAL_SIZE(op);
+ assert(n_fields >= 0);
+ assert(index < n_fields);
+#endif
+ return PyTuple_GET_ITEM(op, index);
}
goto error;
}
- PyObject *value = PyStructSequence_GET_ITEM(obj, i);
+ PyObject *value = PyStructSequence_GetItem((PyObject*)obj, i);
assert(value != NULL);
PyObject *repr = PyObject_Repr(value);
if (repr == NULL) {