Skip to content

Commit 56d6084

Browse files
committed
Merge branch 'jk/upload-pack-bounded-resources'
Various parts of upload-pack has been updated to bound the resource consumption relative to the size of the repository to protect from abusive clients. * jk/upload-pack-bounded-resources: upload-pack: free tree buffers after parsing upload-pack: use PARSE_OBJECT_SKIP_HASH_CHECK in more places upload-pack: always turn off save_commit_buffer upload-pack: disallow object-info capability by default upload-pack: accept only a single packfile-uri line upload-pack: use a strmap for want-ref lines upload-pack: use oidset for deepen_not list upload-pack: switch deepen-not list to an oid_array upload-pack: drop separate v2 "haves" array
2 parents 963a277 + 6cd05e7 commit 56d6084

File tree

10 files changed

+113
-73
lines changed

10 files changed

+113
-73
lines changed

Documentation/config/transfer.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,7 @@ transfer.bundleURI::
121121
information from the remote server (if advertised) and download
122122
bundles before continuing the clone through the Git protocol.
123123
Defaults to `false`.
124+
125+
transfer.advertiseObjectInfo::
126+
When `true`, the `object-info` capability is advertised by
127+
servers. Defaults to false.

Documentation/gitprotocol-v2.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ the 'wanted-refs' section in the server's response as explained below.
346346
want-ref <ref>
347347
Indicates to the server that the client wants to retrieve a
348348
particular ref, where <ref> is the full name of a ref on the
349-
server.
349+
server. It is a protocol error to send want-ref for the
350+
same ref more than once.
350351

351352
If the 'sideband-all' feature is advertised, the following argument can be
352353
included in the client's request:
@@ -361,7 +362,8 @@ included in the client's request:
361362
If the 'packfile-uris' feature is advertised, the following argument
362363
can be included in the client's request as well as the potential
363364
addition of the 'packfile-uris' section in the server's response as
364-
explained below.
365+
explained below. Note that at most one `packfile-uris` line can be sent
366+
to the server.
365367

366368
packfile-uris <comma-separated-list-of-protocols>
367369
Indicates to the server that the client is willing to receive

builtin/upload-pack.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "replace-object.h"
99
#include "upload-pack.h"
1010
#include "serve.h"
11+
#include "commit.h"
1112

1213
static const char * const upload_pack_usage[] = {
1314
N_("git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
@@ -37,6 +38,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
3738

3839
packet_trace_identity("upload-pack");
3940
disable_replace_refs();
41+
save_commit_buffer = 0;
4042

4143
argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);
4244

object.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ struct object *parse_object_with_flags(struct repository *r,
271271
enum parse_object_flags flags)
272272
{
273273
int skip_hash = !!(flags & PARSE_OBJECT_SKIP_HASH_CHECK);
274+
int discard_tree = !!(flags & PARSE_OBJECT_DISCARD_TREE);
274275
unsigned long size;
275276
enum object_type type;
276277
int eaten;
@@ -298,6 +299,17 @@ struct object *parse_object_with_flags(struct repository *r,
298299
return lookup_object(r, oid);
299300
}
300301

302+
/*
303+
* If the caller does not care about the tree buffer and does not
304+
* care about checking the hash, we can simply verify that we
305+
* have the on-disk object with the correct type.
306+
*/
307+
if (skip_hash && discard_tree &&
308+
(!obj || obj->type == OBJ_TREE) &&
309+
oid_object_info(r, oid, NULL) == OBJ_TREE) {
310+
return &lookup_tree(r, oid)->object;
311+
}
312+
301313
buffer = repo_read_object_file(r, oid, &type, &size);
302314
if (buffer) {
303315
if (!skip_hash &&
@@ -311,6 +323,8 @@ struct object *parse_object_with_flags(struct repository *r,
311323
buffer, &eaten);
312324
if (!eaten)
313325
free(buffer);
326+
if (discard_tree && type == OBJ_TREE)
327+
free_tree_buffer((struct tree *)obj);
314328
return obj;
315329
}
316330
return NULL;

object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ void *object_as_type(struct object *obj, enum object_type type, int quiet);
197197
*/
198198
enum parse_object_flags {
199199
PARSE_OBJECT_SKIP_HASH_CHECK = 1 << 0,
200+
PARSE_OBJECT_DISCARD_TREE = 1 << 1,
200201
};
201202
struct object *parse_object(struct repository *r, const struct object_id *oid);
202203
struct object *parse_object_with_flags(struct repository *r,

revision.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,8 @@ static struct object *get_reference(struct rev_info *revs, const char *name,
381381

382382
object = parse_object_with_flags(revs->repo, oid,
383383
revs->verify_objects ? 0 :
384-
PARSE_OBJECT_SKIP_HASH_CHECK);
384+
PARSE_OBJECT_SKIP_HASH_CHECK |
385+
PARSE_OBJECT_DISCARD_TREE);
385386

386387
if (!object) {
387388
if (revs->ignore_missing)

serve.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "trace2.h"
1313

1414
static int advertise_sid = -1;
15+
static int advertise_object_info = -1;
1516
static int client_hash_algo = GIT_HASH_SHA1;
1617

1718
static int always_advertise(struct repository *r UNUSED,
@@ -67,6 +68,17 @@ static void session_id_receive(struct repository *r UNUSED,
6768
trace2_data_string("transfer", NULL, "client-sid", client_sid);
6869
}
6970

71+
static int object_info_advertise(struct repository *r, struct strbuf *value UNUSED)
72+
{
73+
if (advertise_object_info == -1 &&
74+
repo_config_get_bool(r, "transfer.advertiseobjectinfo",
75+
&advertise_object_info)) {
76+
/* disabled by default */
77+
advertise_object_info = 0;
78+
}
79+
return advertise_object_info;
80+
}
81+
7082
struct protocol_capability {
7183
/*
7284
* The name of the capability. The server uses this name when
@@ -135,7 +147,7 @@ static struct protocol_capability capabilities[] = {
135147
},
136148
{
137149
.name = "object-info",
138-
.advertise = always_advertise,
150+
.advertise = object_info_advertise,
139151
.command = cap_object_info,
140152
},
141153
{

t/t5555-http-smart-common.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ test_expect_success 'git upload-pack --advertise-refs: v2' '
131131
fetch=shallow wait-for-done
132132
server-option
133133
object-format=$(test_oid algo)
134-
object-info
135134
0000
136135
EOF
137136

t/t5701-git-serve.sh

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ test_expect_success 'test capability advertisement' '
2020
fetch=shallow wait-for-done
2121
server-option
2222
object-format=$(test_oid algo)
23-
object-info
2423
EOF
2524
cat >expect.trailer <<-EOF &&
2625
0000
@@ -323,6 +322,8 @@ test_expect_success 'unexpected lines are not allowed in fetch request' '
323322
# Test the basics of object-info
324323
#
325324
test_expect_success 'basics of object-info' '
325+
test_config transfer.advertiseObjectInfo true &&
326+
326327
test-tool pkt-line pack >in <<-EOF &&
327328
command=object-info
328329
object-format=$(test_oid algo)
@@ -380,4 +381,25 @@ test_expect_success 'basics of bundle-uri: dies if not enabled' '
380381
test_must_be_empty out
381382
'
382383

384+
test_expect_success 'object-info missing from capabilities when disabled' '
385+
test_config transfer.advertiseObjectInfo false &&
386+
387+
GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
388+
--advertise-capabilities >out &&
389+
test-tool pkt-line unpack <out >actual &&
390+
391+
! grep object.info actual
392+
'
393+
394+
test_expect_success 'object-info commands rejected when disabled' '
395+
test_config transfer.advertiseObjectInfo false &&
396+
397+
test-tool pkt-line pack >in <<-EOF &&
398+
command=object-info
399+
EOF
400+
401+
test_must_fail test-tool serve-v2 --stateless-rpc <in 2>err &&
402+
grep invalid.command err
403+
'
404+
383405
test_done

0 commit comments

Comments
 (0)