Repository: python/cpython
Pull request: gh-104265 Disallow instantiation of `_csv.Reader` and `_csv.Writer`
Fixes #104265 

Set `Py_TPFLAGS_DISALLOW_INSTANTIATION` and unset `Py_TPFLAGS_BASETYPE` flags on `Reader` and `Writer` types to prevent their instantiation and subtyping


<!-- gh-issue-number: gh-104265 -->
* Issue: gh-104265
<!-- /gh-issue-number -->


Problem statement:
`_csv` `Reader` and `Writer` types shouldn't be directly instantiable
The accepted way to create these objects is to use constructor functions `_csv.reader()` and `_csv.writer()` with appropriate arguments. Objects that are created through type constructors `_csv.Reader` and `_csv.Writer` turn out to be not properly initialized, and operations on them easily lead to crash:
```python
>>> import _csv
>>> _csv.Writer().writerow([])
Segmentation fault (core dumped)
```
```python
>>> import _csv
>>> list(_csv.Reader())
Segmentation fault (core dumped)
```
Although this is an internal detail, I'm sure that this should be fixed. I'll submit a PR shortly.
The crash appears on 3.10, 3.11 and current main.

<!-- gh-linked-prs -->
### Linked PRs
* gh-104266
* gh-104278
<!-- /gh-linked-prs -->

Hints from issue discussion:

Commit message: Delete 2023-05-07-16-13-07.gh-issue-104265.fU60bZ.rst

Patch to review:
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index 8fb97bc0c1a1a7..b1b8263ed8c2ea 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -7,10 +7,11 @@
 from io import StringIO
 from tempfile import TemporaryFile
 import csv
+import _csv
 import gc
 import pickle
 from test import support
-from test.support import warnings_helper
+from test.support import warnings_helper, check_disallow_instantiation
 from itertools import permutations
 from textwrap import dedent
 from collections import OrderedDict
@@ -1430,5 +1431,11 @@ def test_subclassable(self):
         # issue 44089
         class Foo(csv.Error): ...
 
+    def test_reader_disallow_instantiation(self):
+        check_disallow_instantiation(self, _csv.Reader)
+
+    def test_writer_disallow_instantiation(self):
+        check_disallow_instantiation(self, _csv.Writer)
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2023-05-07-19-56-45.gh-issue-104265.fVblry.rst b/Misc/NEWS.d/next/Library/2023-05-07-19-56-45.gh-issue-104265.fVblry.rst
new file mode 100644
index 00000000000000..6a31feba22759e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-05-07-19-56-45.gh-issue-104265.fVblry.rst
@@ -0,0 +1 @@
+Prevent possible crash by disallow instantiation of the :class:`!_csv.Reader` and :class:`!_csv.Writer` types. The regression was introduced in 3.10.0a4 with PR 23224 (:issue:`14935`). Patch by Radislav Chugunov.
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 0cde5c5a8bdc68..9ab2ad266c2739 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -1000,7 +1000,7 @@ PyType_Spec Reader_Type_spec = {
     .name = "_csv.reader",
     .basicsize = sizeof(ReaderObj),
     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
-              Py_TPFLAGS_IMMUTABLETYPE),
+              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
     .slots = Reader_Type_slots
 };
 
@@ -1431,7 +1431,7 @@ PyType_Spec Writer_Type_spec = {
     .name = "_csv.writer",
     .basicsize = sizeof(WriterObj),
     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
-              Py_TPFLAGS_IMMUTABLETYPE),
+              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
     .slots = Writer_Type_slots,
 };
 


Code review comments:
diff_hunk: @@ -0,0 +1 @@
+Prevent possible crash by disallow instantiation of the :class:`!_csv.Reader` and :class:`!_csv.Writer` types. The regression was introduced in 3.10.0a4 with PR 23224 (:issue:`14935`). Patch by Radislav Chugunov.
path: Misc/NEWS.d/next/Library/2023-05-07-19-56-45.gh-issue-104265.fVblry.rst
text: @user1:
Fix a typo and break within 79 chars linewidth.

```suggestion
Prevent possible crash by disallowing instantiation of the
:class:`!_csv.Reader` and :class:`!_csv.Writer` types.
The regression was introduced in 3.10.0a4 with PR 23224 (:issue:`14935`).
Patch by Radislav Chugunov.
```