receive-pack: allow a maximum input size to be specified
Receive-pack feeds its input to either index-pack or unpack-objects, which will happily accept as many bytes as a sender is willing to provide. Let's allow an arbitrary cutoff point where we will stop writing bytes to disk. Cleaning up what has already been written to disk is a related problem that is not addressed by this patch. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Aug 24, 2016 at 20:41 UTC
c08db5a2d0d5c0cf371168e621d5929005b1abf8
4 files changed
+76
Documentation/config.txt
+6
@@ -2517,6 +2517,12 @@ receive.unpackLimit::
2517
especially on slow filesystems. If not set, the value of
2518
`transfer.unpackLimit` is used instead.
2519
2520
+receive.maxInputSize::
2521
+ If the size of the incoming pack stream is larger than this
2522
+ limit, then git-receive-pack will error out, instead of
2523
+ accepting the pack file. If not set or set to 0, then the size
2524
+ is unlimited.
2525
+
2526
receive.denyDeletes::
2527
If set to true, git-receive-pack will deny a ref update that deletes
2528
the ref. Use this to prevent such a ref deletion via a push.
Documentation/git-receive-pack.txt
+3
@@ -33,6 +33,9 @@ post-update hooks found in the Documentation/howto directory.
33
option, which tells it if updates to a ref should be denied if they
34
are not fast-forwards.
35
36
+A number of other receive.* config options are available to tweak
37
+its behavior, see linkgit:git-config[1].
38
+
39
OPTIONS
40
-------
41
<directory>::
builtin/receive-pack.c
+12
@@ -46,6 +46,7 @@ static int transfer_unpack_limit = -1;
46
static int advertise_atomic_push = 1;
47
static int advertise_push_options;
48
static int unpack_limit = 100;
49
+static off_t max_input_size;
50
static int report_status;
51
static int use_sideband;
52
static int use_atomic;
@@ -212,6 +213,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
213
return 0;
214
}
215
216
+ if (strcmp(var, "receive.maxinputsize") == 0) {
217
+ max_input_size = git_config_int64(var, value);
218
+ return 0;
219
+ }
220
+
221
return git_default_config(var, value, cb);
222
}
223
@@ -1648,6 +1654,9 @@ static const char *unpack(int err_fd, struct shallow_info *si)
1654
if (fsck_objects)
1655
argv_array_pushf(&child.args, "--strict%s",
1656
fsck_msg_types.buf);
1657
+ if (max_input_size)
1658
+ argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
1659
+ (uintmax_t)max_input_size);
1660
child.no_stdout = 1;
1661
child.err = err_fd;
1662
child.git_cmd = 1;
@@ -1676,6 +1685,9 @@ static const char *unpack(int err_fd, struct shallow_info *si)
1685
fsck_msg_types.buf);
1686
if (!reject_thin)
1687
argv_array_push(&child.args, "--fix-thin");
1688
+ if (max_input_size)
1689
+ argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
1690
+ (uintmax_t)max_input_size);
1691
child.out = -1;
1692
child.err = err_fd;
1693
child.git_cmd = 1;
t/t5546-receive-limits.sh
new
+55
@@ -0,0 +1,55 @@
1
+#!/bin/sh
2
+
3
+test_description='check receive input limits'
4
+. ./test-lib.sh
5
+
6
+# Let's run tests with different unpack limits: 1 and 10000
7
+# When the limit is 1, `git receive-pack` will call `git index-pack`.
8
+# When the limit is 10000, `git receive-pack` will call `git unpack-objects`.
9
+
10
+test_pack_input_limit () {
11
+ case "$1" in
12
+ index) unpack_limit=1 ;;
13
+ unpack) unpack_limit=10000 ;;
14
+ esac
15
+
16
+ test_expect_success 'prepare destination repository' '
17
+ rm -fr dest &&
18
+ git --bare init dest
19
+ '
20
+
21
+ test_expect_success "set unpacklimit to $unpack_limit" '
22
+ git --git-dir=dest config receive.unpacklimit "$unpack_limit"
23
+ '
24
+
25
+ test_expect_success 'setting receive.maxInputSize to 512 rejects push' '
26
+ git --git-dir=dest config receive.maxInputSize 512 &&
27
+ test_must_fail git push dest HEAD
28
+ '
29
+
30
+ test_expect_success 'bumping limit to 4k allows push' '
31
+ git --git-dir=dest config receive.maxInputSize 4k &&
32
+ git push dest HEAD
33
+ '
34
+
35
+ test_expect_success 'prepare destination repository (again)' '
36
+ rm -fr dest &&
37
+ git --bare init dest
38
+ '
39
+
40
+ test_expect_success 'lifting the limit allows push' '
41
+ git --git-dir=dest config receive.maxInputSize 0 &&
42
+ git push dest HEAD
43
+ '
44
+}
45
+
46
+test_expect_success "create known-size (1024 bytes) commit" '
47
+ test-genrandom foo 1024 >one-k &&
48
+ git add one-k &&
49
+ test_commit one-k
50
+'
51
+
52
+test_pack_input_limit index
53
+test_pack_input_limit unpack
54
+
55
+test_done