Commit 7cb705cbf7749ba32f9163599fa056b5f4f0ad18

Patrick Steinhardt 2017-10-06T12:05:26

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.

diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index d51238f..aecfece 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -273,7 +273,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)
@@ -285,6 +285,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;
@@ -297,16 +300,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;