You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Double DECREF / use-after-free in pygit2_refdb_backend_write #1471
pygit2_refdb_backend_write() passes owned objects to Py_BuildValue() with the N format (which steals the reference), then decrefs the same objects again in its cleanup block — a double DECREF that can lead to a use-after-free.
File: src/refdb_backend.c
Function: pygit2_refdb_backend_write
Relevant code:
PyObject*args=NULL, *ref=NULL, *who=NULL, *old=NULL;
if ((ref=wrap_reference((git_reference*)_ref, NULL)) ==NULL)
goto euser;
if ((who=build_signature(NULL, _who, "utf-8")) ==NULL)
goto euser;
if ((old=git_oid_to_python(_old)) ==NULL)
goto euser;
if ((args=Py_BuildValue("(NNNsNs)", ref,
force ? Py_True : Py_False,
who, message, old, old_target)) ==NULL)
goto euser;
PyObject_CallObject(be->write, args);
err=git_error_for_exc();
out:
Py_DECREF(ref);
Py_DECREF(who);
Py_DECREF(old);
Py_DECREF(args);
returnerr;
euser:
err=GIT_EUSER;
goto out;
Three problems:
Double DECREF. The N format steals a reference, so on success ref, who, and old are owned by the tuple args. The out: block then calls Py_DECREF(ref), Py_DECREF(who), Py_DECREF(old)andPy_DECREF(args) (which decrefs each element again during tuple deallocation). Each of the three objects is released one time too many.
Stolen singleton.force ? Py_True : Py_False is a borrowed singleton reference. Passing it with N (without Py_INCREF) transfers a reference the function never owned, underflowing the singleton's refcount.
Non-X cleanup on the error path. All four locals are initialized to NULL, but the euser path jumps to out:, which uses Py_DECREF rather than Py_XDECREF. If an early allocation fails (e.g. wrap_reference returns NULL), the cleanup dereferences a NULL pointer and crashes instead of returning GIT_EUSER.
Activity
Fix refcounting bugs in the refdb backend write callback