diff options
context:
space:
mode:
-rw-r--r--source/ui-clone.c8
-rwxr-xr-xtests/t0303-robustness.sh13
2 files changed, 21 insertions, 0 deletions
diff --git a/source/ui-clone.c b/source/ui-clone.c
index 833c170..832a056 100644
--- a/source/ui-clone.c
+++ b/source/ui-clone.c
@@ -166,6 +166,14 @@ void cgit_clone_objects(void)
return;
}
+ // The alternates file names directories on the server's disk, which a
+ // client fetching over http cannot reach, so only the http form that
+ // is written for such clients goes out.
+ if (!strcmp(ctx.qry.path, "info/alternates")) {
+ cgit_print_error_page(404, "Not Found", "Not found");
+ return;
+ }
+
if (!path_is_safe(ctx.qry.path))
goto err;
diff --git a/tests/t0303-robustness.sh b/tests/t0303-robustness.sh
index 8d64c1e..be98644 100755
--- a/tests/t0303-robustness.sh
+++ b/tests/t0303-robustness.sh
@@ -494,6 +494,19 @@ test_expect_success 'the dumb transport sends a file with its size' '
cmp body repos/rob/.git/objects/pack/$pack
'
+# The alternates file lists object directories by their path on the server,
+# which a client fetching over http cannot use and should not learn.
+test_expect_success 'the dumb transport withholds the alternates file' '
+ mkdir -p repos/rob/.git/objects/info &&
+ echo "$PWD/repos/foo/.git/objects" >repos/rob/.git/objects/info/alternates &&
+ robq "url=rob/objects/info/alternates" >tmp &&
+ grep "^Status: 404" tmp &&
+ ! grep "repos/foo" tmp &&
+ rm repos/rob/.git/objects/info/alternates &&
+ robq "url=rob/objects/info/packs" >tmp &&
+ grep "^Status: 200" tmp
+'
+
test_expect_success 'a symlink whose target is a large blob is listed without it' '
big=$(head -c 5000 /dev/zero | tr "\0" a | git -C repos/rob hash-object -w --stdin) &&
(