summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@github.com>2016-06-29 09:35:56 -0400
committerGitHub <noreply@github.com>2016-06-29 09:35:56 -0400
commitd88e500133aefcf144fef7c4bcd6f073b2d50cf4 (patch)
tree7e3916a8af105f709a7c3d1863641eda10001158
parent20302aa43738a972e0bd2e2ee6ae479208427b31 (diff)
parent217667028918d1993d22508881e5df8fa2755e6a (diff)
downloadlibgit2-d88e500133aefcf144fef7c4bcd6f073b2d50cf4.tar.gz
Merge pull request #3842 from pks-t/pks/double-free
blame: increment reference count for origin's commit
-rw-r--r--src/blame_git.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/blame_git.c b/src/blame_git.c
index 700207edb..96785c75b 100644
--- a/src/blame_git.c
+++ b/src/blame_git.c
@@ -37,25 +37,27 @@ static void origin_decref(git_blame__origin *o)
static int make_origin(git_blame__origin **out, git_commit *commit, const char *path)
{
git_blame__origin *o;
+ git_object *blob;
size_t path_len = strlen(path), alloc_len;
int error = 0;
+ if ((error = git_object_lookup_bypath(&blob, (git_object*)commit,
+ path, GIT_OBJ_BLOB)) < 0)
+ return error;
+
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*o), path_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
o = git__calloc(1, alloc_len);
GITERR_CHECK_ALLOC(o);
o->commit = commit;
+ o->blob = (git_blob *) blob;
o->refcnt = 1;
strcpy(o->path, path);
- if (!(error = git_object_lookup_bypath((git_object**)&o->blob, (git_object*)commit,
- path, GIT_OBJ_BLOB))) {
- *out = o;
- } else {
- origin_decref(o);
- }
- return error;
+ *out = o;
+
+ return 0;
}
/* Locate an existing origin or create a new one. */
@@ -529,8 +531,16 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
goto finish;
porigin = find_origin(blame, p, origin);
- if (!porigin)
+ if (!porigin) {
+ /*
+ * We only have to decrement the parent's
+ * reference count when no porigin has
+ * been created, as otherwise the commit
+ * is assigned to the created object.
+ */
+ git_commit_free(p);
continue;
+ }
if (porigin->blob && origin->blob &&
!git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) {
pass_whole_blame(blame, origin, porigin);