Skip to content

Commit 5e19a7f

Browse files
committed
refs: preserve the owning refdb when duping reference
This fixes a segfault in git_reference_owner on references returned from git_reference__read_head and git_reference_dup ones.
1 parent 0eca423 commit 5e19a7f

File tree

3 files changed

+9
-0
lines changed

3 files changed

+9
-0
lines changed

src/refs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ int git_reference_dup(git_reference **dest, git_reference *source)
115115

116116
GITERR_CHECK_ALLOC(*dest);
117117

118+
(*dest)->db = source->db;
119+
GIT_REFCOUNT_INC((*dest)->db);
120+
118121
return 0;
119122
}
120123

src/refs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ int git_reference_lookup_resolved(
116116
* with the given name pointing to the reference pointed to by
117117
* the file. If it is not a symbolic reference, it will return
118118
* the resolved reference.
119+
*
120+
* Note that because the refdb is not involved for symbolic references, they
121+
* won't be owned, hence you should either not make the returned reference
122+
* 'externally visible', or perform the lookup before returning it to the user.
119123
*/
120124
int git_reference__read_head(
121125
git_reference **out,

tests/refs/dup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ void test_refs_dup__direct(void)
2121
cl_git_pass(git_reference_dup(&b, a));
2222

2323
cl_assert(git_reference_cmp(a, b) == 0);
24+
cl_assert(git_reference_owner(b) == g_repo);
2425

2526
git_reference_free(b);
2627
git_reference_free(a);
@@ -34,6 +35,7 @@ void test_refs_dup__symbolic(void)
3435
cl_git_pass(git_reference_dup(&b, a));
3536

3637
cl_assert(git_reference_cmp(a, b) == 0);
38+
cl_assert(git_reference_owner(b) == g_repo);
3739

3840
git_reference_free(b);
3941
git_reference_free(a);

0 commit comments

Comments
 (0)