Commit 6ae6491e5f6033a23dfdb0fb010da74ef5413c0f

Etienne Samson 2018-07-06T22:24:16

smart: don't dereference a NULL pkt pointer By clarifying what detect_caps returns on empty/missing packet, we can be sure there are actually refs to process. The old code could blindly dereference `first`, which might have been NULL. Reported by Coverity, CID 1393614

diff --git a/src/transports/smart.c b/src/transports/smart.c
index 1800995..ff66f91 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -280,20 +280,23 @@ static int git_smart__connect(
 
 	/* Detect capabilities */
 	if ((error = git_smart__detect_caps(first, &t->caps, &symrefs)) == 0) {
-		goto cleanup;
-	}
+		/* If the only ref in the list is capabilities^{} with OID_ZERO, remove it */
+		if (1 == t->refs.length && !strcmp(first->head.name, "capabilities^{}") &&
+			git_oid_iszero(&first->head.oid)) {
+			git_vector_clear(&t->refs);
+			git_pkt_free((git_pkt *)first);
+		}
 
-	/* If the only ref in the list is capabilities^{} with OID_ZERO, remove it */
-	if (1 == t->refs.length && !strcmp(first->head.name, "capabilities^{}") &&
-	    git_oid_iszero(&first->head.oid)) {
-		git_vector_clear(&t->refs);
-		git_pkt_free((git_pkt *)first);
+		/* Keep a list of heads for _ls */
+		git_smart__update_heads(t, &symrefs);
+	} else if (error == GIT_ENOTFOUND) {
+		/* There was no ref packet received, or the cap list was empty */
+		error = 0;
+	} else {
+		giterr_set(GITERR_NET, "invalid response");
+		goto cleanup;
 	}
 
-	/* Keep a list of heads for _ls */
-	git_smart__update_heads(t, &symrefs);
-
-
 	if (t->rpc && (error = git_smart__reset_stream(t, false)) < 0)
 		goto cleanup;
 
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index b114e18..750ae6d 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -142,7 +142,7 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
 
 	/* No refs or capabilites, odd but not a problem */
 	if (pkt == NULL || pkt->capabilities == NULL)
-		return 0;
+		return GIT_ENOTFOUND;
 
 	ptr = pkt->capabilities;
 	while (ptr != NULL && *ptr != '\0') {