From 74ba1098efd0cd43a5806b4992eec17732330818 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Sat, 17 Oct 2026 12:53:18 -1000 Subject: Keep snapshot members from starting at a slash A name that was all suffix, such as .tar, settled on a ref called v with an empty prefix, and an empty snapshot-prefix did the same for a snapshot asked for by id, so every member of the archive started at /. --- source/ui-snapshot.c | 10 +++++++++- tests/t0110-snapshot.sh | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/source/ui-snapshot.c b/source/ui-snapshot.c index 8762407..3c00f66 100644 --- a/source/ui-snapshot.c +++ b/source/ui-snapshot.c @@ -29,7 +29,9 @@ static int write_archive_format(const char *format_arg, const char *hex, const c strvec_push(&argv, "snapshot"); strvec_push(&argv, format_arg); - if (prefix) { + // An empty prefix means none, since the slash added below would root + // every member of the archive at /. + if (prefix && *prefix) { struct strbuf buf = STRBUF_INIT; strbuf_addstr(&buf, prefix); @@ -370,6 +372,12 @@ void cgit_print_snapshot(const char *head, const char *hex, const char *filename cgit_print_error_page(404, "Not Found", "Not found"); return; } + // A name that is all suffix names no revision, though the lookup below + // would settle on a ref called v. + if (!hex && dwim && strlen(filename) == strlen(f->suffix)) { + cgit_print_error_page(404, "Not Found", "Not found"); + return; + } if (!hex && dwim) { hex = ref_from_filename(ctx.repo, filename, f); if (!hex) { diff --git a/tests/t0110-snapshot.sh b/tests/t0110-snapshot.sh index 4852e7b..ec0a0b8 100755 --- a/tests/t0110-snapshot.sh +++ b/tests/t0110-snapshot.sh @@ -146,4 +146,25 @@ test_expect_success 'a real case collision keeps the v on both tags' ' ! grep "vtags-1.0.tar.gz" tmp ' +# A name that is all suffix names no revision, and an empty snapshot-prefix +# gives the members no leading directory rather than a leading slash. +test_expect_success 'a snapshot name with nothing before its suffix is refused' ' + git -C repos/vtags branch v HEAD && + sed "s/^snapshots=tar.gz$/snapshots=tar/" vtagsrc >vtagstarrc && + CGIT_CONFIG="$PWD/vtagstarrc" QUERY_STRING="url=vtags/snapshot/.tar" cgit >tmp && + grep "^Status: 404" tmp +' + +test_expect_success 'an empty snapshot-prefix puts no slash ahead of the members' ' + { + cat vtagstarrc && + echo "repo.snapshot-prefix=" + } >noprefixrc && + CGIT_CONFIG="$PWD/noprefixrc" QUERY_STRING="url=vtags/snapshot/vtags.tar&id=master" cgit >tmp && + strip_headers noprefix.tar && + tar -tf noprefix.tar >members && + grep "^file-1$" members && + ! grep "^/" members +' + test_done -- cgit