aboutsummaryrefslogtreecommitdiff
path: root/connect.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2020-06-08 18:06:30 -0700
committerJunio C Hamano <gitster@pobox.com>2020-06-08 18:06:30 -0700
commitb37fd14beb39b9f545bd72e42e1bdbb00bad4b3d (patch)
tree73b0516cbdf8593e0fb045d56809db3285275d05 /connect.c
parentded44afa023c981d803b56f42284ed0597a174ee (diff)
parentb0df0c16ead4c5512d506dcbbdf31194d992803c (diff)
downloadgit-b37fd14beb39b9f545bd72e42e1bdbb00bad4b3d.tar.xz
Merge branch 'dl/remote-curl-deadlock-fix'
On-the-wire protocol v2 easily falls into a deadlock between the remote-curl helper and the fetch-pack process when the server side prematurely throws an error and disconnects. The communication has been updated to make it more robust. * dl/remote-curl-deadlock-fix: stateless-connect: send response end packet pkt-line: define PACKET_READ_RESPONSE_END remote-curl: error on incomplete packet pkt-line: extern packet_length() transport: extract common fetch_pack() call remote-curl: remove label indentation remote-curl: fix typo
Diffstat (limited to 'connect.c')
-rw-r--r--connect.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/connect.c b/connect.c
index 23013c6344..0df45a1108 100644
--- a/connect.c
+++ b/connect.c
@@ -127,6 +127,7 @@ enum protocol_version discover_version(struct packet_reader *reader)
die_initial_contact(0);
case PACKET_READ_FLUSH:
case PACKET_READ_DELIM:
+ case PACKET_READ_RESPONSE_END:
version = protocol_v0;
break;
case PACKET_READ_NORMAL:
@@ -310,6 +311,7 @@ struct ref **get_remote_heads(struct packet_reader *reader,
state = EXPECTING_DONE;
break;
case PACKET_READ_DELIM:
+ case PACKET_READ_RESPONSE_END:
die(_("invalid packet"));
}
@@ -404,10 +406,21 @@ out:
return ret;
}
+void check_stateless_delimiter(int stateless_rpc,
+ struct packet_reader *reader,
+ const char *error)
+{
+ if (!stateless_rpc)
+ return; /* not in stateless mode, no delimiter expected */
+ if (packet_reader_read(reader) != PACKET_READ_RESPONSE_END)
+ die("%s", error);
+}
+
struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
struct ref **list, int for_push,
const struct argv_array *ref_prefixes,
- const struct string_list *server_options)
+ const struct string_list *server_options,
+ int stateless_rpc)
{
int i;
*list = NULL;
@@ -444,6 +457,9 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
if (reader->status != PACKET_READ_FLUSH)
die(_("expected flush after ref listing"));
+ check_stateless_delimiter(stateless_rpc, reader,
+ _("expected response end packet after ref listing"));
+
return list;
}