Skip to content

Reference leaks in the add_err macro failure paths (LDAPinit_constants) #622

Description

@K-ANOY

The add_err macro used by LDAPinit_constants() returns -1 on several failure paths without releasing the exc exception object (and, on one path, nobj). These are import-time ownership bugs.

File: Modules/constants.c

Function: LDAPinit_constants (macro add_err)

Relevant code:

#define add_err(n) do {  \
    exc = PyErr_NewException("ldap." #n, LDAPexception_class, NULL);  \
    if (exc == NULL) return -1;  \
    nobj = PyLong_FromLong(LDAP_##n); \
    if (nobj == NULL) return -1; \                                    /* leaks exc */
    if (PyObject_SetAttrString(exc, "errnum", nobj) != 0) return -1; \ /* leaks exc and nobj */
    Py_DECREF(nobj); \
    errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = exc;  \
    if (PyModule_AddObject(m, #n, exc) != 0) return -1;  \             /* leaks exc */
    Py_INCREF(exc);  \
} while (0)
  • If PyLong_FromLong() fails, exc is leaked.
  • If PyObject_SetAttrString() fails, both exc and nobj are leaked.
  • If PyModule_AddObject() fails, exc is leaked (PyModule_AddObject only
    steals the reference on success). Note errobjects[...] = exc stores a raw
    pointer and does not own a reference.

Severity note: every one of these paths returns -1, which aborts module import, so the leaked objects have no lasting effect in practice — this is a correctness/hygiene issue on an import-abort path, not a runtime leak. Listed for completeness; lowest priority of the python-ldap findings.

Suggested fix: release owned references before returning, e.g. via a cleanup
label:

    nobj = PyLong_FromLong(LDAP_##n); \
    if (nobj == NULL) { Py_DECREF(exc); return -1; } \
    if (PyObject_SetAttrString(exc, "errnum", nobj) != 0) { \
        Py_DECREF(nobj); Py_DECREF(exc); return -1; \
    } \
    Py_DECREF(nobj); \
    errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = exc;  \
    if (PyModule_AddObject(m, #n, exc) != 0) { Py_DECREF(exc); return -1; } \
    Py_INCREF(exc);  \

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions