From 8e369d364518d668898f2142f8daf402e2cd3ddc Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Sun, 12 Apr 2026 00:44:45 +0200 Subject: [PATCH] [3.13] gh-145105: Fix crash in csv.reader with re-entrant iterator (GH-145106) (#148405) 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. (cherry picked from commit 20994b1809f9c162e4cae01a5af08bd492ede9f9) Co-authored-by: Ramin Farajpour Cami --- Lib/test/test_csv.py | 27 +++++++++++++++++++ ...0.gh-issue-145105.csv-reader-reentrant.rst | 2 ++ Modules/_csv.c | 6 +++++ 3 files changed, 35 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index ce5c03659f19..6ea388313bbf 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -552,6 +552,33 @@ class Test_Csv(unittest.TestCase): 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 000000000000..bc61cc43a5aa --- /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 0b7ff2575fcf..755d005f4d82 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -957,6 +957,12 @@ Reader_iternext(ReaderObj *self) 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); -- 2.47.3