Skip to content

Error-path reference leaks in Repository.listall_branches and Tree.diff_to_index #1480

Description

@K-ANOY

Two functions leak an owned object on one early-error path that returns directly instead of going through the cleanup they already have a few lines below.

Repository_listall_branches_impl()

File: src/repository.c, line 1424

list = PyList_New(0);
if (list == NULL)
    return NULL;

if ((err = git_branch_iterator_new(&iter, self->repo, list_flags)) < 0)
    return Error_set(err);          /* list leaked */

Every other error exit in this function releases the list — the loop body jumps to error:, and the post-loop failure does Py_CLEAR(list) — so this one return is the odd one out.

Suggested fix:

if ((err = git_branch_iterator_new(&iter, self->repo, list_flags)) < 0) {
    Py_DECREF(list);
    return Error_set(err);
}

Tree_diff_to_index()

File: src/tree.c, line 269

PyObject *py_idx_ptr = PyObject_GetAttrString(py_idx, "_pointer");
if (!py_idx_ptr)
    return NULL;

/* Here we need to do the opposite conversion from the _pointer getters */
if (PyBytes_AsStringAndSize(py_idx_ptr, &buffer, &length))
    goto error;

if (length != sizeof(git_index *)) {
    PyErr_SetString(PyExc_TypeError, "passed value is not a pointer");
    goto error;
}

index = *((git_index **) buffer);

/* Call git_diff_tree_to_index */
if (Object__load((Object*)self) == NULL) { return NULL; } // Lazy load

The two checks above it use the error: label, which does Py_DECREF(py_idx_ptr); the lazy-load failure returns directly and leaks py_idx_ptr.

Suggested fix:

if (Object__load((Object*)self) == NULL) { goto error; } // Lazy load

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions