Skip to content

_csv: DIALECT_GETATTR macro silently masks non-AttributeError exceptions #145966

Closed

Description

@raminfp

Bug report

Bug description:

In Modules/_csv.c, the DIALECT_GETATTR macro in dialect_new() calls PyErr_Clear() unconditionally when PyObject_GetAttrString() fails. This silently swallows all exception types including MemoryError, KeyboardInterrupt, RuntimeError, etc.

https://github.com/python/cpython/blob/main/Modules/_csv.c#L500-L507

#define DIALECT_GETATTR(v, n)                            \
    do {                                                 \
        if (v == NULL) {                                 \
            v = PyObject_GetAttrString(dialect, n);      \
            if (v == NULL)                               \
                PyErr_Clear();                           \
        }                                                \
    } while (0)

Only AttributeError (attribute not found) should be cleared. Other exceptions should propagate.

Reproducer

import csv, io

class MyDialect:
    @property
    def delimiter(self):
        raise MemoryError("OOM")
    quotechar = '"'
    escapechar = None
    doublequote = True
    skipinitialspace = False
    quoting = csv.QUOTE_MINIMAL
    lineterminator = '\r\n'
    strict = False

# Expected: raises MemoryError (was swallowed)
w = csv.writer(io.StringIO(), dialect=MyDialect())
w.writerow(['a', 'b'])
print(w.dialect.delimiter)  # ',' 

All 8 dialect attributes are affected: delimiter, doublequote, escapechar, lineterminator, quotechar, quoting, skipinitialspace, strict.

Fix

#define DIALECT_GETATTR(v, n)                            \
    do {                                                 \
        if (v == NULL) {                                 \
            v = PyObject_GetAttrString(dialect, n);      \
            if (v == NULL) {                             \
                if (PyErr_ExceptionMatches(PyExc_AttributeError)) \
                    PyErr_Clear();                       \
                else                                     \
                    goto err;                            \
            }                                            \
        }                                                \
    } while (0)

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. StanFromIreland commented on Mar 15, 2026

    @StanFromIreland
    Member

    Do you want to write a patch?

  2. raminfp commented on Mar 15, 2026

    @raminfp
    ContributorAuthor

    @StanFromIreland Sure, done.

  3. added a commit that references this issue on Mar 17, 2026
  4. encukou commented on Mar 17, 2026

    @encukou
    Member

    Thank you @raminfp for the fix, and @picnixz for the review!

    This is a behaviour change; I think it's safer to skip backporting.

  5. added a commit that references this issue on Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions