Plug memory leaks
This patch is mostly about making sure that we free the copies of what we have, as well as making sure that we can free it. The IndexEntry forgot to free its path, but it also used a pointer to python-owned memory, which could be freed at any time. MergeResult completely lacked a deallocator. Signature needs to make sure we can free the enocoding, and not to set an owner when we own the memory (in this case for the default signature). The repository needs to get rid of its reference to the object list when returning. The transfer progress callback needs to decref the stats object.
This commit is contained in:
@@ -623,8 +623,9 @@ IndexEntry_init(IndexEntry *self, PyObject *args, PyObject *kwds)
|
||||
return -1;
|
||||
|
||||
memset(&self->entry, 0, sizeof(struct git_index_entry));
|
||||
if (c_path)
|
||||
self->entry.path = c_path;
|
||||
self->entry.path = strdup(c_path);
|
||||
if (!self->entry.path)
|
||||
return -1;
|
||||
|
||||
if (id)
|
||||
git_oid_cpy(&self->entry.oid, &id->oid);
|
||||
@@ -638,6 +639,7 @@ IndexEntry_init(IndexEntry *self, PyObject *args, PyObject *kwds)
|
||||
void
|
||||
IndexEntry_dealloc(IndexEntry *self)
|
||||
{
|
||||
free(self->entry.path);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
|
@@ -50,6 +50,14 @@ git_merge_result_to_python(git_merge_result *merge_result)
|
||||
return (PyObject*) py_merge_result;
|
||||
}
|
||||
|
||||
void
|
||||
MergeResult_dealloc(MergeResult *self)
|
||||
{
|
||||
git_merge_result_free(self->result);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(MergeResult_is_uptodate__doc__, "Is up to date");
|
||||
|
||||
PyObject *
|
||||
@@ -99,7 +107,7 @@ PyTypeObject MergeResultType = {
|
||||
"_pygit2.MergeResult", /* tp_name */
|
||||
sizeof(MergeResult), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
0, /* tp_dealloc */
|
||||
(destructor)MergeResult_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@@ -175,6 +175,7 @@ transfer_progress_cb(const git_transfer_progress *stats, void *data)
|
||||
return -1;
|
||||
|
||||
ret = PyObject_CallFunctionObjArgs(remote->transfer_progress, py_stats, NULL);
|
||||
Py_DECREF(py_stats);
|
||||
if (!ret)
|
||||
return -1;
|
||||
|
||||
|
@@ -139,6 +139,7 @@ Repository_as_iter(Repository *self)
|
||||
git_odb *odb;
|
||||
int err;
|
||||
PyObject *accum = PyList_New(0);
|
||||
PyObject *ret;
|
||||
|
||||
err = git_repository_odb(&odb, self->repo);
|
||||
if (err < 0)
|
||||
@@ -151,7 +152,10 @@ Repository_as_iter(Repository *self)
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
return PyObject_GetIter(accum);
|
||||
ret = PyObject_GetIter(accum);
|
||||
Py_DECREF(accum);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1345,7 +1349,7 @@ Repository_default_signature__get__(Repository *self)
|
||||
if ((err = git_signature_default(&sig, self->repo)) < 0)
|
||||
return Error_set(err);
|
||||
|
||||
return build_signature((Object*) self, sig, "utf-8");
|
||||
return build_signature(NULL, sig, "utf-8");
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Repository_checkout_head__doc__,
|
||||
|
@@ -83,11 +83,12 @@ Signature_init(Signature *self, PyObject *args, PyObject *kwds)
|
||||
void
|
||||
Signature_dealloc(Signature *self)
|
||||
{
|
||||
if (self->obj)
|
||||
/* self->obj is the owner of the git_signature, so we musn't free it */
|
||||
if (self->obj) {
|
||||
Py_CLEAR(self->obj);
|
||||
else {
|
||||
git_signature_free((git_signature*)self->signature);
|
||||
free((char*)self->encoding);
|
||||
} else {
|
||||
git_signature_free((git_signature *) self->signature);
|
||||
free(self->encoding);
|
||||
}
|
||||
|
||||
PyObject_Del(self);
|
||||
@@ -224,12 +225,23 @@ build_signature(Object *obj, const git_signature *signature,
|
||||
Signature *py_signature;
|
||||
|
||||
py_signature = PyObject_New(Signature, &SignatureType);
|
||||
if (!py_signature)
|
||||
goto on_error;
|
||||
|
||||
if (py_signature) {
|
||||
Py_INCREF(obj);
|
||||
py_signature->obj = obj;
|
||||
py_signature->signature = signature;
|
||||
py_signature->encoding = encoding;
|
||||
py_signature->encoding = NULL;
|
||||
if (encoding) {
|
||||
py_signature->encoding = strdup(encoding);
|
||||
if (!py_signature->encoding)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
Py_XINCREF(obj);
|
||||
py_signature->obj = obj;
|
||||
py_signature->signature = signature;
|
||||
|
||||
return (PyObject*)py_signature;
|
||||
|
||||
on_error:
|
||||
git_signature_free((git_signature *) signature);
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -191,7 +191,7 @@ typedef struct {
|
||||
PyObject_HEAD
|
||||
Object *obj;
|
||||
const git_signature *signature;
|
||||
const char *encoding;
|
||||
char *encoding;
|
||||
} Signature;
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user