Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions bundle-uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "remote.h"
#include "trace2.h"
#include "odb.h"
#include "transport.h"
#include "url.h"

static struct {
enum bundle_list_heuristic heuristic;
Expand Down Expand Up @@ -890,11 +892,59 @@ int fetch_bundle_uri(struct repository *r, const char *uri,
return result;
}

/* protocol of 'uri', or "file" if it has none (bare/UNC/relative path) */
static void bundle_uri_protocol(const char *uri, struct strbuf *out)
{
const char *p = uri;

while (is_urlschemechar(p == uri, *p))
p++;
strbuf_reset(out);
if (p > uri && starts_with(p, "://"))
strbuf_add(out, uri, p - uri);
else
strbuf_addstr(out, "file");
}

/* Drop advertised URIs whose protocol is not allowed (see protocol.*.allow). */
static void sanitize_bundle_list(struct bundle_list *list)
{
struct remote_bundle_info **skipped;
size_t nr = 0, i;
struct remote_bundle_info *info;
struct hashmap_iter iter;
struct strbuf proto = STRBUF_INIT;

ALLOC_ARRAY(skipped, hashmap_get_size(&list->bundles));
hashmap_for_each_entry(&list->bundles, &iter, info, ent) {
if (!info->uri)
continue;
bundle_uri_protocol(info->uri, &proto);
/* advertised URIs are not user-provided */
if (!is_transport_allowed(proto.buf, 0)) {
warning(_("skipping bundle URI '%s': protocol '%s' "
"is not allowed"), info->uri, proto.buf);
skipped[nr++] = info;
}
}
strbuf_release(&proto);

for (i = 0; i < nr; i++) {
hashmap_remove(&list->bundles, &skipped[i]->ent, NULL);
clear_remote_bundle_info(skipped[i], NULL);
free(skipped[i]);
}

free(skipped);
}

int fetch_bundle_list(struct repository *r, struct bundle_list *list)
{
int result;
struct bundle_list global_list;

sanitize_bundle_list(list);

/*
* If the creationToken heuristic is used, then the URIs
* advertised by 'list' are not nested lists and instead
Expand Down
56 changes: 56 additions & 0 deletions t/lib-bundle-uri-protocol.sh
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,59 @@ test_expect_success "test bundle-uri with $BUNDLE_URI_PROTOCOL:// using protocol
>actual &&
test_cmp_config_output expect actual
'

# Advertised bundle URIs are subject to protocol.*.allow; "file" (and bare or
# UNC paths) is denied by default, so such a URI must be skipped, not fetched.
advertise_uri () {
test_config -C "$BUNDLE_URI_PARENT" bundle.version 1 &&
test_config -C "$BUNDLE_URI_PARENT" bundle.mode all &&
test_config -C "$BUNDLE_URI_PARENT" bundle.payload.uri "$1"
}

ignores_advertised_uri () {
rm -rf victim &&
advertise_uri "$1" &&
git -c transfer.bundleURI=true -c protocol.version=2 \
clone "$BUNDLE_URI_REPO_URI" victim &&
git -C victim for-each-ref refs/bundles/ >refs &&
test_must_be_empty refs
}

test_expect_success "create bundle to advertise" '
git -C "$BUNDLE_URI_PARENT" bundle create "$PWD/payload.bundle" main
'

test_expect_success "ignore non-HTTP(S) bundle URI with $BUNDLE_URI_PROTOCOL://" '
ignores_advertised_uri "$PWD/payload.bundle" &&
ignores_advertised_uri "file://$PWD/payload.bundle"
'

test_expect_success "protocol.file.allow=always honors file bundle URI with $BUNDLE_URI_PROTOCOL://" '
rm -rf victim &&
advertise_uri "$PWD/payload.bundle" &&
git -c transfer.bundleURI=true -c protocol.version=2 \
-c protocol.file.allow=always \
clone "$BUNDLE_URI_REPO_URI" victim &&
git -C victim rev-parse --verify refs/bundles/heads/main
'

# same path via a UNC administrative share (cf. t5580-unc-paths.sh)
if test_have_prereq CYGWIN
then
UNCPATH="$(cygpath -aw .)"
elif test_have_prereq MINGW
then
UNCPATH="$(pwd)"
fi
case "$UNCPATH" in
[A-Za-z]:*)
WITHOUTDRIVE="${UNCPATH#?:}"
UNCPATH="//localhost/${UNCPATH%%:*}\$$WITHOUTDRIVE"
test -d "$UNCPATH" && test_set_prereq ADMIN_UNC
;;
esac

test_expect_success ADMIN_UNC "ignore UNC bundle URI with $BUNDLE_URI_PROTOCOL://" '
ignores_advertised_uri "$UNCPATH/payload.bundle" &&
ignores_advertised_uri "file://$UNCPATH/payload.bundle"
'
Loading