@matheusbsbs / matheus-bagliano / commits / 4845b77245
Fork 0

upload-pack: handle unexpected delim packets

When processing the arguments list for a v2 ls-refs or fetch command, we loop like this: while (packet_reader_read(request) != PACKET_READ_FLUSH) { const char *arg = request->line; ...handle arg... } to read and handle packets until we see a flush. The hidden assumption here is that anything except PACKET_READ_FLUSH will give us valid packet data to read. But that's not true; PACKET_READ_DELIM or PACKET_READ_EOF will leave packet->line as NULL, and we'll segfault trying to look at it. Instead, we should follow the more careful model demonstrated on the client side (e.g., in process_capabilities_v2): keep looping as long as we get normal packets, and then make sure that we broke out of the loop due to a real flush. That fixes the segfault and correctly diagnoses any unexpected input from the client. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Mar 27, 2020 at 04:03 UTC 4845b7724582a315eb4eb13d5058f85d21798e94
3 files changed +41 -2
ls-refs.c
+4 -1
@@ -93,7 +93,7 @@ int ls_refs(struct repository *r, struct argv_array *keys,
93
94 git_config(ls_refs_config, NULL);
95
96 - while (packet_reader_read(request) != PACKET_READ_FLUSH) {
96 + while (packet_reader_read(request) == PACKET_READ_NORMAL) {
97 const char *arg = request->line;
98 const char *out;
99
@@ -105,6 +105,9 @@ int ls_refs(struct repository *r, struct argv_array *keys,
105 argv_array_push(&data.prefixes, out);
106 }
107
108 + if (request->status != PACKET_READ_FLUSH)
109 + die(_("expected flush after ls-refs arguments"));
110 +
111 head_ref_namespaced(send_ref, &data);
112 for_each_namespaced_ref(send_ref, &data);
113 packet_flush(1);
t/t5704-protocol-violations.sh new
+33
@@ -0,0 +1,33 @@
1 +#!/bin/sh
2 +
3 +test_description='Test responses to violations of the network protocol. In most
4 +of these cases it will generally be acceptable for one side to break off
5 +communications if the other side says something unexpected. We are mostly
6 +making sure that we do not segfault or otherwise behave badly.'
7 +. ./test-lib.sh
8 +
9 +test_expect_success 'extra delim packet in v2 ls-refs args' '
10 + {
11 + packetize command=ls-refs &&
12 + printf 0001 &&
13 + # protocol expects 0000 flush here
14 + printf 0001
15 + } >input &&
16 + test_must_fail env GIT_PROTOCOL=version=2 \
17 + git upload-pack . <input 2>err &&
18 + test_i18ngrep "expected flush after ls-refs arguments" err
19 +'
20 +
21 +test_expect_success 'extra delim packet in v2 fetch args' '
22 + {
23 + packetize command=fetch &&
24 + printf 0001 &&
25 + # protocol expects 0000 flush here
26 + printf 0001
27 + } >input &&
28 + test_must_fail env GIT_PROTOCOL=version=2 \
29 + git upload-pack . <input 2>err &&
30 + test_i18ngrep "expected flush after fetch arguments" err
31 +'
32 +
33 +test_done
upload-pack.c
+4 -1
@@ -1252,7 +1252,7 @@ static void process_args(struct packet_reader *request,
1252 struct upload_pack_data *data,
1253 struct object_array *want_obj)
1254 {
1255 - while (packet_reader_read(request) != PACKET_READ_FLUSH) {
1255 + while (packet_reader_read(request) == PACKET_READ_NORMAL) {
1256 const char *arg = request->line;
1257 const char *p;
1258
@@ -1321,6 +1321,9 @@ static void process_args(struct packet_reader *request,
1321 /* ignore unknown lines maybe? */
1322 die("unexpected line: '%s'", arg);
1323 }
1324 +
1325 + if (request->status != PACKET_READ_FLUSH)
1326 + die(_("expected flush after fetch arguments"));
1327 }
1328
1329 static int process_haves(struct oid_array *haves, struct oid_array *common,