https://github.com/python/cpython/commit/20994b1809f9c162e4cae01a5af08bd492ede9f9
commit: 20994b1809f9c162e4cae01a5af08bd492ede9f9
branch: main
author: Ramin Farajpour Cami <[email protected]>
committer: gpshead <[email protected]>
date: 2026-04-11T15:18:02-07:00
summary:
gh-145105: Fix crash in csv.reader with re-entrant iterator (GH-145106)
When a custom iterator calls next() on the same csv.reader from
within __next__, the inner iteration sets self->fields to NULL.
The outer iteration then crashes in parse_save_field() by passing
NULL to PyList_Append.
Add a guard after PyIter_Next() to detect that fields was set to
NULL by a re-entrant call, and raise csv.Error instead of crashing.
files:
A
Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst
M Lib/test/test_csv.py
M Modules/_csv.c
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index 2e5b72742c3f41..7327c1bd5f5053 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -553,6 +553,33 @@ def test_roundtrip_escaped_unquoted_newlines(self):
self.assertEqual(row, rows[i])
+ def test_reader_reentrant_iterator(self):
+ # gh-145105: re-entering the reader from the iterator must not crash.
+ class ReentrantIter:
+ def __init__(self):
+ self.reader = None
+ self.n = 0
+ def __iter__(self):
+ return self
+ def __next__(self):
+ self.n += 1
+ if self.n == 1:
+ try:
+ next(self.reader)
+ except StopIteration:
+ pass
+ return "a,b"
+ if self.n == 2:
+ return "x"
+ raise StopIteration
+
+ it = ReentrantIter()
+ reader = csv.reader(it)
+ it.reader = reader
+ with self.assertRaises(csv.Error):
+ next(reader)
+
+
class TestDialectRegistry(unittest.TestCase):
def test_registry_badargs(self):
self.assertRaises(TypeError, csv.list_dialects, None)
diff --git
a/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst
b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst
new file mode 100644
index 00000000000000..bc61cc43a5aa33
--- /dev/null
+++
b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst
@@ -0,0 +1,2 @@
+Fix crash in :mod:`csv` reader when iterating with a re-entrant iterator
+that calls :func:`next` on the same reader from within ``__next__``.
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 9d6190a11c4b10..a7fcc78e058f05 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -965,6 +965,12 @@ Reader_iternext_lock_held(PyObject *op)
Py_DECREF(lineobj);
return NULL;
}
+ if (self->fields == NULL) {
+ PyErr_SetString(module_state->error_obj,
+ "iterator has already advanced the reader");
+ Py_DECREF(lineobj);
+ return NULL;
+ }
++self->line_num;
kind = PyUnicode_KIND(lineobj);
data = PyUnicode_DATA(lineobj);
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]