Skip to content

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

@raminfp

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

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions