transports: smart: fix memory leak when skipping symbolic refs When we setup the revision walk for negotiating references with a remote, we iterate over all references, ignoring tags and symbolic references. While skipping over symbolic references, we forget to free the looked up reference, resulting in a memory leak when the next iteration simply overwrites the variable. Fix that issue by freeing the reference at the beginning of each iteration and collapsing return paths for error and success.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 8146fa1..eab10aa 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -270,7 +270,7 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
git_revwalk *walk = NULL;
git_strarray refs;
unsigned int i;
- git_reference *ref;
+ git_reference *ref = NULL;
int error;
if ((error = git_reference_list(&refs, repo)) < 0)
@@ -282,6 +282,9 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
git_revwalk_sorting(walk, GIT_SORT_TIME);
for (i = 0; i < refs.count; ++i) {
+ git_reference_free(ref);
+ ref = NULL;
+
/* No tags */
if (!git__prefixcmp(refs.strings[i], GIT_REFS_TAGS_DIR))
continue;
@@ -294,16 +297,13 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
if ((error = git_revwalk_push(walk, git_reference_target(ref))) < 0)
goto on_error;
-
- git_reference_free(ref);
}
- git_strarray_free(&refs);
*out = walk;
- return 0;
on_error:
- git_revwalk_free(walk);
+ if (error)
+ git_revwalk_free(walk);
git_reference_free(ref);
git_strarray_free(&refs);
return error;