Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
Accept NULL in Add() and AddSteal()
  • Loading branch information
vstinner committed Oct 11, 2025
commit 8e7025fd6650605763ef6f0d33541238b173b6d7
5 changes: 3 additions & 2 deletions Doc/c-api/tuple.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,9 @@ object.

Add an item to *writer*.

On success, return ``0``.
On error, set an exception and return ``-1``.
* On success, return ``0``.
* If *item* is ``NULL``, return ``-1`` with an exception set.
* On error, set an exception and return ``-1``.

.. c:function:: int PyTupleWriter_AddSteal(PyTupleWriter *writer, PyObject *item)

Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_capi/test_tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@ def check_add(self, name):
add(i)
self.assertEqual(writer.finish(), tuple(range(1024)))

writer = self.create_writer(1)
add = getattr(writer, name)
with self.assertRaises(SystemError):
add(NULL)

def test_add(self):
# Test PyTupleWriter_Add()
self.check_add('add')
Expand Down
6 changes: 5 additions & 1 deletion Modules/_testcapi/tuple.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ writer_check(WriterObject *self)
static PyObject*
writer_add(PyObject *self_raw, PyObject *item)
{
NULLABLE(item);

WriterObject *self = (WriterObject *)self_raw;
if (writer_check(self) < 0) {
return NULL;
Expand All @@ -222,12 +224,14 @@ writer_add(PyObject *self_raw, PyObject *item)
static PyObject*
writer_add_steal(PyObject *self_raw, PyObject *item)
{
NULLABLE(item);

WriterObject *self = (WriterObject *)self_raw;
if (writer_check(self) < 0) {
return NULL;
}

if (PyTupleWriter_AddSteal(self->writer, Py_NewRef(item)) < 0) {
if (PyTupleWriter_AddSteal(self->writer, Py_XNewRef(item)) < 0) {
return NULL;
}
Py_RETURN_NONE;
Expand Down
7 changes: 2 additions & 5 deletions Objects/abstract.c
Original file line number Diff line number Diff line change
Expand Up @@ -2024,11 +2024,8 @@ PySequence_Tuple(PyObject *v)
}

for (;;) {
PyObject *item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred()) {
goto fail;
}
PyObject *item;
if (PyIter_NextItem(it, &item) == 0) {
break;
}
if (PyTupleWriter_AddSteal(writer, item) < 0) {
Comment thread
vstinner marked this conversation as resolved.
Expand Down
14 changes: 14 additions & 0 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,13 @@ PyTupleWriter_Create(Py_ssize_t size)
int
PyTupleWriter_Add(PyTupleWriter *writer, PyObject *item)
{
if (item == NULL) {
if (!PyErr_Occurred()) {
PyErr_BadInternalCall();
}
return -1;
}

if (writer->size >= writer->allocated) {
if (_PyTupleWriter_SetSize(writer, writer->size + 1, 1) < 0) {
return -1;
Expand All @@ -1323,6 +1330,13 @@ PyTupleWriter_Add(PyTupleWriter *writer, PyObject *item)
int
PyTupleWriter_AddSteal(PyTupleWriter *writer, PyObject *item)
{
if (item == NULL) {
if (!PyErr_Occurred()) {
PyErr_BadInternalCall();
}
return -1;
}

if (writer->size >= writer->allocated) {
if (_PyTupleWriter_SetSize(writer, writer->size + 1, 1) < 0) {
Py_DECREF(item);
Expand Down