Skip to content

Commit fab8267

Browse files
[3.13] gh-146056: Fix repr() for lists containing NULLs (GH-146129) (GH-146155) (GH-146271)
(cherry picked from commit 0f2246b) (cherry picked from commit 7965133) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 5d71935 commit fab8267

File tree

6 files changed

+24
-3
lines changed

6 files changed

+24
-3
lines changed

Doc/c-api/file.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,12 @@ the :mod:`io` APIs instead.
123123
124124
Write object *obj* to file object *p*. The only supported flag for *flags* is
125125
:c:macro:`Py_PRINT_RAW`; if given, the :func:`str` of the object is written
126-
instead of the :func:`repr`. Return ``0`` on success or ``-1`` on failure; the
127-
appropriate exception will be set.
126+
instead of the :func:`repr`.
127+
128+
If *obj* is ``NULL``, write the string ``"<NULL>"``.
128129
130+
Return ``0`` on success or ``-1`` on failure; the
131+
appropriate exception will be set.
129132
130133
.. c:function:: int PyFile_WriteString(const char *s, PyObject *p)
131134

Doc/c-api/object.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ Object Protocol
319319
representation on success, ``NULL`` on failure. This is the equivalent of the
320320
Python expression ``repr(o)``. Called by the :func:`repr` built-in function.
321321
322+
If argument is ``NULL``, return the string ``'<NULL>'``.
323+
322324
.. versionchanged:: 3.4
323325
This function now includes a debug assertion to help ensure that it
324326
does not silently discard an active exception.
@@ -333,6 +335,8 @@ Object Protocol
333335
a string similar to that returned by :c:func:`PyObject_Repr` in Python 2.
334336
Called by the :func:`ascii` built-in function.
335337
338+
If argument is ``NULL``, return the string ``'<NULL>'``.
339+
336340
.. index:: string; PyObject_Str (C function)
337341
338342
@@ -343,6 +347,8 @@ Object Protocol
343347
Python expression ``str(o)``. Called by the :func:`str` built-in function
344348
and, therefore, by the :func:`print` function.
345349
350+
If argument is ``NULL``, return the string ``'<NULL>'``.
351+
346352
.. versionchanged:: 3.4
347353
This function now includes a debug assertion to help ensure that it
348354
does not silently discard an active exception.
@@ -358,6 +364,8 @@ Object Protocol
358364
a TypeError is raised when *o* is an integer instead of a zero-initialized
359365
bytes object.
360366
367+
If argument is ``NULL``, return the :class:`bytes` object ``b'<NULL>'``.
368+
361369
362370
.. c:function:: int PyObject_IsSubclass(PyObject *derived, PyObject *cls)
363371

Lib/test/test_capi/test_list.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,10 @@ def test_list_extend(self):
352352
# CRASHES list_extend(NULL, [])
353353
# CRASHES list_extend([], NULL)
354354

355+
def test_uninitialized_list_repr(self):
356+
lst = _testlimitedcapi.list_new(3)
357+
self.assertEqual(repr(lst), '[<NULL>, <NULL>, <NULL>]')
358+
355359

356360
if __name__ == "__main__":
357361
unittest.main()

Lib/test/test_capi/test_tuple.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,5 +257,10 @@ def test__tuple_resize(self):
257257
self.assertRaises(SystemError, resize, [1, 2, 3], 0, False)
258258
self.assertRaises(SystemError, resize, NULL, 0, False)
259259

260+
def test_uninitialized_tuple_repr(self):
261+
tup = _testlimitedcapi.tuple_new(3)
262+
self.assertEqual(repr(tup), '(<NULL>, <NULL>, <NULL>)')
263+
264+
260265
if __name__ == "__main__":
261266
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :func:`repr` for lists containing ``NULL``\ s.

Objects/listobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ list_repr_impl(PyListObject *v)
604604
so must refetch the list size on each iteration. */
605605
for (i = 0; i < Py_SIZE(v); ++i) {
606606
/* Hold a strong reference since repr(item) can mutate the list */
607-
item = Py_NewRef(v->ob_item[i]);
607+
item = Py_XNewRef(v->ob_item[i]);
608608

609609
if (i > 0) {
610610
if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)

0 commit comments

Comments
 (0)