Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
24 changes: 24 additions & 0 deletions Lib/test/test_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,30 @@ def __next__(self):
with self.assertRaises(csv.Error):
next(reader)

def test_reader_reentrant_iterator_eof_in_quoted_field(self):
# gh-157379: the re-entrant call leaves an open quoted field, then
# the outer call reaches the end of input.
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:
next(self.reader)
raise StopIteration
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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix a crash in :mod:`csv` reader when a re-entrant iterator reaches the end
of input while a quoted field is still open.
4 changes: 4 additions & 0 deletions Modules/_csv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,10 @@ Reader_iternext_lock_held(PyObject *op)
if (self->dialect->strict)
PyErr_SetString(module_state->error_obj,
"unexpected end of data");
else if (self->fields == NULL)
PyErr_SetString(module_state->error_obj,
"iterator has already advanced "
"the reader");
else if (parse_save_field(self) >= 0)
break;
}
Expand Down
Loading