https://github.com/python/cpython/commit/dc24b8a6d42231ebc821baeda662e1168b52aa26
commit: dc24b8a6d42231ebc821baeda662e1168b52aa26
branch: main
author: Ramin Farajpour Cami <[email protected]>
committer: encukou <[email protected]>
date: 2026-03-17T16:08:53+01:00
summary:

gh-145966: Fix _csv DIALECT_GETATTR macro silently masking non-AttributeError 
exceptions (GH-145974)

The DIALECT_GETATTR macro in dialect_new() unconditionally called
PyErr_Clear() when PyObject_GetAttrString() failed, which suppressed
all exceptions including MemoryError, KeyboardInterrupt, and
RuntimeError. Now only AttributeError is cleared; other exceptions
propagate via the existing error handling path.

Co-authored-by: Bénédikt Tran <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.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 df79840088abc3..2e5b72742c3f41 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -1280,6 +1280,19 @@ class mydialect(csv.Dialect):
                     self.assertRaises(ValueError, create_invalid, field_name, 
" ",
                                       skipinitialspace=True)
 
+    def test_dialect_getattr_non_attribute_error_propagates(self):
+        # gh-145966: non-AttributeError exceptions raised by __getattr__
+        # during dialect attribute lookup must propagate, not be silenced.
+        class BadDialect:
+            def __getattr__(self, name):
+                raise RuntimeError("boom")
+
+        with self.assertRaises(RuntimeError):
+            csv.reader([], dialect=BadDialect())
+
+        with self.assertRaises(RuntimeError):
+            csv.writer(StringIO(), dialect=BadDialect())
+
 
 class TestSniffer(unittest.TestCase):
     sample1 = """\
diff --git 
a/Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.rst 
b/Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.rst
new file mode 100644
index 00000000000000..c0d4907ada073c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.rst
@@ -0,0 +1,2 @@
+Non-:exc:`AttributeError` exceptions raised during dialect attribute lookup
+in :mod:`csv` are no longer silently suppressed.
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 1f41976e95fdb1..c48f44c0f07867 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -497,13 +497,13 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject 
*kwargs)
     Py_XINCREF(skipinitialspace);
     Py_XINCREF(strict);
     if (dialect != NULL) {
-#define DIALECT_GETATTR(v, n)                            \
-        do {                                             \
-            if (v == NULL) {                             \
-                v = PyObject_GetAttrString(dialect, n);  \
-                if (v == NULL)                           \
-                    PyErr_Clear();                       \
-            }                                            \
+#define DIALECT_GETATTR(v, n)                                               \
+        do {                                                                \
+            if (v == NULL) {                                                \
+                if (PyObject_GetOptionalAttrString(dialect, n, &v) < 0) {   \
+                    goto err;                                               \
+                }                                                           \
+            }                                                               \
         } while (0)
         DIALECT_GETATTR(delimiter, "delimiter");
         DIALECT_GETATTR(doublequote, "doublequote");

_______________________________________________
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]

Reply via email to