1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-13 05:16:09 +02:00
git/t/t5701-git-serve.sh
Jeff King 7f0e4f6ac2 ls-refs: ignore very long ref-prefix counts
Because each "ref-prefix" capability from the client comes in its own
pkt-line, there's no limit to the number of them that a misbehaving
client may send. We read them all into a strvec, which means the client
can waste arbitrary amounts of our memory by just sending us "ref-prefix
foo" over and over.

One possible solution is to just drop the connection when the limit is
reached. If we set it high enough, then only misbehaving or malicious
clients would hit it. But "high enough" is vague, and it's unfriendly if
we guess wrong and a legitimate client hits this.

But we can do better. Since supporting the ref-prefix capability is
optional anyway, the client has to further cull the response based on
their own patterns. So we can simply ignore the patterns once we cross a
certain threshold. Note that we have to ignore _all_ patterns, not just
the ones past our limit (since otherwise we'd send too little data).

The limit here is fairly arbitrary, and probably much higher than anyone
would need in practice. It might be worth limiting it further, if only
because we check it linearly (so with "m" local refs and "n" patterns,
we do "m * n" string comparisons). But if we care about optimizing this,
an even better solution may be a more advanced data structure anyway.

I didn't bother making the limit configurable, since it's so high and
since Git should behave correctly in either case. It wouldn't be too
hard to do, but it makes both the code and documentation more complex.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-09-15 12:25:19 -07:00

301 lines
6.9 KiB
Bash
Executable File

#!/bin/sh
test_description='test protocol v2 server commands'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
test_expect_success 'test capability advertisement' '
test_oid_cache <<-EOF &&
wrong_algo sha1:sha256
wrong_algo sha256:sha1
EOF
cat >expect <<-EOF &&
version 2
agent=git/$(git version | cut -d" " -f3)
ls-refs=unborn
fetch=shallow wait-for-done
server-option
object-format=$(test_oid algo)
object-info
0000
EOF
GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
--advertise-capabilities >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'stateless-rpc flag does not list capabilities' '
# Empty request
test-tool pkt-line pack >in <<-EOF &&
0000
EOF
test-tool serve-v2 --stateless-rpc >out <in &&
test_must_be_empty out &&
# EOF
test-tool serve-v2 --stateless-rpc >out &&
test_must_be_empty out
'
test_expect_success 'request invalid capability' '
test-tool pkt-line pack >in <<-EOF &&
foobar
0000
EOF
test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
test_i18ngrep "unknown capability" err
'
test_expect_success 'request with no command' '
test-tool pkt-line pack >in <<-EOF &&
agent=git/test
object-format=$(test_oid algo)
0000
EOF
test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
test_i18ngrep "no command requested" err
'
test_expect_success 'request invalid command' '
test-tool pkt-line pack >in <<-EOF &&
command=foo
object-format=$(test_oid algo)
agent=git/test
0000
EOF
test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
test_i18ngrep "invalid command" err
'
test_expect_success 'wrong object-format' '
test-tool pkt-line pack >in <<-EOF &&
command=fetch
agent=git/test
object-format=$(test_oid wrong_algo)
0000
EOF
test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in &&
test_i18ngrep "mismatched object format" err
'
# Test the basics of ls-refs
#
test_expect_success 'setup some refs and tags' '
test_commit one &&
git branch dev main &&
test_commit two &&
git symbolic-ref refs/heads/release refs/heads/main &&
git tag -a -m "annotated tag" annotated-tag
'
test_expect_success 'basics of ls-refs' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
object-format=$(test_oid algo)
0000
EOF
cat >expect <<-EOF &&
$(git rev-parse HEAD) HEAD
$(git rev-parse refs/heads/dev) refs/heads/dev
$(git rev-parse refs/heads/main) refs/heads/main
$(git rev-parse refs/heads/release) refs/heads/release
$(git rev-parse refs/tags/annotated-tag) refs/tags/annotated-tag
$(git rev-parse refs/tags/one) refs/tags/one
$(git rev-parse refs/tags/two) refs/tags/two
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'basic ref-prefixes' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
object-format=$(test_oid algo)
0001
ref-prefix refs/heads/main
ref-prefix refs/tags/one
0000
EOF
cat >expect <<-EOF &&
$(git rev-parse refs/heads/main) refs/heads/main
$(git rev-parse refs/tags/one) refs/tags/one
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'refs/heads prefix' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
object-format=$(test_oid algo)
0001
ref-prefix refs/heads/
0000
EOF
cat >expect <<-EOF &&
$(git rev-parse refs/heads/dev) refs/heads/dev
$(git rev-parse refs/heads/main) refs/heads/main
$(git rev-parse refs/heads/release) refs/heads/release
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'ignore very large set of prefixes' '
# generate a large number of ref-prefixes that we expect
# to match nothing; the value here exceeds TOO_MANY_PREFIXES
# from ls-refs.c.
{
echo command=ls-refs &&
echo object-format=$(test_oid algo) &&
echo 0001 &&
perl -le "print \"ref-prefix refs/heads/\$_\" for (1..65536)" &&
echo 0000
} |
test-tool pkt-line pack >in &&
# and then confirm that we see unmatched prefixes anyway (i.e.,
# that the prefix was not applied).
cat >expect <<-EOF &&
$(git rev-parse HEAD) HEAD
$(git rev-parse refs/heads/dev) refs/heads/dev
$(git rev-parse refs/heads/main) refs/heads/main
$(git rev-parse refs/heads/release) refs/heads/release
$(git rev-parse refs/tags/annotated-tag) refs/tags/annotated-tag
$(git rev-parse refs/tags/one) refs/tags/one
$(git rev-parse refs/tags/two) refs/tags/two
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'peel parameter' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
object-format=$(test_oid algo)
0001
peel
ref-prefix refs/tags/
0000
EOF
cat >expect <<-EOF &&
$(git rev-parse refs/tags/annotated-tag) refs/tags/annotated-tag peeled:$(git rev-parse refs/tags/annotated-tag^{})
$(git rev-parse refs/tags/one) refs/tags/one
$(git rev-parse refs/tags/two) refs/tags/two
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'symrefs parameter' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
object-format=$(test_oid algo)
0001
symrefs
ref-prefix refs/heads/
0000
EOF
cat >expect <<-EOF &&
$(git rev-parse refs/heads/dev) refs/heads/dev
$(git rev-parse refs/heads/main) refs/heads/main
$(git rev-parse refs/heads/release) refs/heads/release symref-target:refs/heads/main
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'sending server-options' '
test-tool pkt-line pack >in <<-EOF &&
command=ls-refs
object-format=$(test_oid algo)
server-option=hello
server-option=world
0001
ref-prefix HEAD
0000
EOF
cat >expect <<-EOF &&
$(git rev-parse HEAD) HEAD
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_expect_success 'unexpected lines are not allowed in fetch request' '
git init server &&
test-tool pkt-line pack >in <<-EOF &&
command=fetch
object-format=$(test_oid algo)
0001
this-is-not-a-command
0000
EOF
(
cd server &&
test_must_fail test-tool serve-v2 --stateless-rpc
) <in >/dev/null 2>err &&
grep "unexpected line: .this-is-not-a-command." err
'
# Test the basics of object-info
#
test_expect_success 'basics of object-info' '
test-tool pkt-line pack >in <<-EOF &&
command=object-info
object-format=$(test_oid algo)
0001
size
oid $(git rev-parse two:two.t)
oid $(git rev-parse two:two.t)
0000
EOF
cat >expect <<-EOF &&
size
$(git rev-parse two:two.t) $(wc -c <two.t | xargs)
$(git rev-parse two:two.t) $(wc -c <two.t | xargs)
0000
EOF
test-tool serve-v2 --stateless-rpc <in >out &&
test-tool pkt-line unpack <out >actual &&
test_cmp expect actual
'
test_done