Commit 1fd267608803f401a72380d26fbaf57ac3f4fe38

Edward Thomson 2018-04-17T23:33:06

Merge pull request #4618 from tiennou/fix/pwned-references refs: preserve the owning refdb when duping reference

diff --git a/src/refs.c b/src/refs.c
index 550963e..c429683 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -115,6 +115,9 @@ int git_reference_dup(git_reference **dest, git_reference *source)
 
 	GITERR_CHECK_ALLOC(*dest);
 
+	(*dest)->db = source->db;
+	GIT_REFCOUNT_INC((*dest)->db);
+
 	return 0;
 }
 
diff --git a/src/refs.h b/src/refs.h
index 5149c75..84daf8b 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -116,6 +116,10 @@ int git_reference_lookup_resolved(
  * with the given name pointing to the reference pointed to by
  * the file. If it is not a symbolic reference, it will return
  * the resolved reference.
+ *
+ * Note that because the refdb is not involved for symbolic references, they
+ * won't be owned, hence you should either not make the returned reference
+ * 'externally visible', or perform the lookup before returning it to the user.
  */
 int git_reference__read_head(
 	git_reference **out,
diff --git a/tests/refs/dup.c b/tests/refs/dup.c
index 0fc635a..8a89cd9 100644
--- a/tests/refs/dup.c
+++ b/tests/refs/dup.c
@@ -21,6 +21,7 @@ void test_refs_dup__direct(void)
 	cl_git_pass(git_reference_dup(&b, a));
 
 	cl_assert(git_reference_cmp(a, b) == 0);
+	cl_assert(git_reference_owner(b) == g_repo);
 
 	git_reference_free(b);
 	git_reference_free(a);
@@ -34,6 +35,7 @@ void test_refs_dup__symbolic(void)
 	cl_git_pass(git_reference_dup(&b, a));
 
 	cl_assert(git_reference_cmp(a, b) == 0);
+	cl_assert(git_reference_owner(b) == g_repo);
 
 	git_reference_free(b);
 	git_reference_free(a);
diff --git a/tests/worktree/repository.c b/tests/worktree/repository.c
index 5c7595c..ca56413 100644
--- a/tests/worktree/repository.c
+++ b/tests/worktree/repository.c
@@ -27,6 +27,7 @@ void test_worktree_repository__head(void)
 	cl_git_pass(git_reference_lookup(&ref, fixture.repo, "refs/heads/testrepo-worktree"));
 	cl_git_pass(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree"));
 	cl_assert(git_reference_cmp(ref, head) == 0);
+	cl_assert(git_reference_owner(ref) == fixture.repo);
 
 	git_reference_free(ref);
 	git_reference_free(head);