Commit eb398797c (connect: advertized capability is not a ref,
2016-09-09) taught 'get_remote_heads()' to recognize that the
'capabilities^{}' line isn't a ref but required that the
'capabilities^{}' line came during the first response from the server.
A future patch will introduce a version string sent by the server during
its first response which can then cause a client to unnecessarily die if
a 'capabilities^{}' line sent as the first ref.

Teach 'get_remote_heads()' to instead die if a 'capabilities^{}' line is
sent after a ref.

Reported-by: Miguel Alcon <mal...@google.com>
Signed-off-by: Brandon Williams <bmw...@google.com>
---
This is a fix to the bug we found when internally deploying this series.  It
just makes it so that a capability line wont cause a client to error out if its
not the first response, because it won't be the first response come protocol
v1.

 connect.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/connect.c b/connect.c
index df56c0cbf..af5096ec6 100644
--- a/connect.c
+++ b/connect.c
@@ -124,10 +124,11 @@ struct ref **get_remote_heads(int in, char *src_buf, 
size_t src_len,
         * response does not necessarily mean an ACL problem, though.
         */
        int saw_response;
+       int seen_ref;
        int got_dummy_ref_with_capabilities_declaration = 0;

        *list = NULL;
-       for (saw_response = 0; ; saw_response = 1) {
+       for (saw_response = 0, seen_ref = 0; ; saw_response = 1) {
                struct ref *ref;
                struct object_id old_oid;
                char *name;
@@ -165,6 +166,8 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t 
src_len,

                name_len = strlen(name);
                if (len != name_len + GIT_SHA1_HEXSZ + 1) {
+                       if (seen_ref)
+                               ; /* NEEDSWORK: Error out for multiple 
capabilities lines? */
                        free(server_capabilities);
                        server_capabilities = xstrdup(name + name_len + 1);
                }
@@ -175,7 +178,7 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t 
src_len,
                }

                if (!strcmp(name, "capabilities^{}")) {
-                       if (saw_response)
+                       if (seen_ref)
                                die("protocol error: unexpected 
capabilities^{}");
                        if (got_dummy_ref_with_capabilities_declaration)
                                die("protocol error: multiple capabilities^{}");
@@ -193,6 +196,7 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t 
src_len,
                oidcpy(&ref->old_oid, &old_oid);
                *list = ref;
                list = &ref->next;
+               seen_ref = 1;
        }

        annotate_refs_with_symref_info(*orig_list);
--
2.14.1.821.g8fa685d3b7-goog

Reply via email to