Commit 12232a5ea0bbf26f174ba017ef506df11042c037

Edward Thomson 2018-06-27T17:19:37

Merge pull request #4698 from nelhage/fix-leaks Fix assorted leaks found via fuzzing

diff --git a/src/transports/smart.c b/src/transports/smart.c
index 7a5dd61..fdc9c11 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -167,8 +167,10 @@ int git_smart__update_heads(transport_smart *t, git_vector *symrefs)
 			git_vector_foreach(symrefs, j, spec) {
 				git_buf_clear(&buf);
 				if (git_refspec_src_matches(spec, ref->head.name) &&
-				    !(error = git_refspec_transform(&buf, spec, ref->head.name)))
+				    !(error = git_refspec_transform(&buf, spec, ref->head.name))) {
+					git__free(ref->head.symref_target);
 					ref->head.symref_target = git_buf_detach(&buf);
+				}
 			}
 
 			git_buf_dispose(&buf);
@@ -277,8 +279,10 @@ static int git_smart__connect(
 		return error;
 
 	/* Detect capabilities */
-	if (git_smart__detect_caps(first, &t->caps, &symrefs) < 0)
+	if (git_smart__detect_caps(first, &t->caps, &symrefs) < 0) {
+		free_symrefs(&symrefs);
 		return -1;
+	}
 
 	/* If the only ref in the list is capabilities^{} with OID_ZERO, remove it */
 	if (1 == t->refs.length && !strcmp(first->head.name, "capabilities^{}") &&
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index 43c7874..d7de5bd 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -375,7 +375,7 @@ static int32_t parse_len(const char *line)
 					num[k] = '.';
 				}
 			}
-			
+
 			giterr_set(GITERR_NET, "invalid hex digit in length: '%s'", num);
 			return -1;
 		}
@@ -488,6 +488,9 @@ int git_pkt_parse_line(
 
 void git_pkt_free(git_pkt *pkt)
 {
+	if (pkt == NULL) {
+		return;
+	}
 	if (pkt->type == GIT_PKT_REF) {
 		git_pkt_ref *p = (git_pkt_ref *) pkt;
 		git__free(p->head.name);
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 442a10f..948b93b 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -323,27 +323,30 @@ on_error:
 static int wait_while_ack(gitno_buffer *buf)
 {
 	int error;
-	git_pkt_ack *pkt = NULL;
+	git_pkt *pkt = NULL;
+	git_pkt_ack *ack = NULL;
 
 	while (1) {
-		git__free(pkt);
+		git_pkt_free(pkt);
 
-		if ((error = recv_pkt((git_pkt **)&pkt, NULL, buf)) < 0)
+		if ((error = recv_pkt(&pkt, NULL, buf)) < 0)
 			return error;
 
 		if (pkt->type == GIT_PKT_NAK)
 			break;
+		if (pkt->type != GIT_PKT_ACK)
+			continue;
 
-		if (pkt->type == GIT_PKT_ACK &&
-		    (pkt->status != GIT_ACK_CONTINUE &&
-		     pkt->status != GIT_ACK_COMMON &&
-		     pkt->status != GIT_ACK_READY)) {
-			git__free(pkt);
-			return 0;
+		ack = (git_pkt_ack*)pkt;
+
+		if (ack->status != GIT_ACK_CONTINUE &&
+		    ack->status != GIT_ACK_COMMON &&
+		    ack->status != GIT_ACK_READY) {
+			break;
 		}
 	}
 
-	git__free(pkt);
+	git_pkt_free(pkt);
 	return 0;
 }
 
@@ -621,7 +624,8 @@ int git_smart__download_pack(
 			}
 		}
 
-		git__free(pkt);
+		git_pkt_free(pkt);
+
 		if (error < 0)
 			goto done;