ls-refs: ignore very long ref-prefix counts
commit7f0e4f6ac28b7a9494f3affd1336244d4fb0fe38
authorJeff King <peff@peff.net>
Wed, 15 Sep 2021 18:35:31 +0000 (15 14:35 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Sep 2021 19:25:19 +0000 (15 12:25 -0700)
tree1031a1b8c1c014efe9d055b3a3c6e2fe6a236858
parentf0a35c9ce52ade69311ab3b8cb111e145eb7b875
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>
ls-refs.c
t/t5701-git-serve.sh