From 6c28482dbbec61808606f1e3a7d6dc9a226cea5d Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Sat, 17 Oct 2026 12:53:18 -1000 Subject: Say why an oversized readme leaves about empty A readme past max-blob-size is never read, which left the about page with an empty block and no word of why. --- source/ui-blob.c | 2 +- source/ui-blob.h | 7 +++++++ source/ui-summary.c | 10 ++++++++-- tests/t0303-robustness.sh | 15 +++++++++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/source/ui-blob.c b/source/ui-blob.c index e1503e0..4690bb5 100644 --- a/source/ui-blob.c +++ b/source/ui-blob.c @@ -133,7 +133,7 @@ int cgit_print_file(char *path, const char *head, int file_only, int html_escape if (type == OBJ_BAD) return -1; if (cgit_blob_too_large(size)) - return -1; + return -2; buf = odb_read_object(the_repository->objects, &oid, &type, &size); if (!buf) return -1; diff --git a/source/ui-blob.h b/source/ui-blob.h index 58e0abb..2c10c55 100644 --- a/source/ui-blob.h +++ b/source/ui-blob.h @@ -9,7 +9,14 @@ #define CGIT_UI_BLOB_H extern int cgit_ref_path_exists(const char *path, const char *ref, int file_only); + +/* + * Write the file at path in head, escaped when html_escape is set. The return + * is 0 once it is written, -2 when it is past max-blob-size, and -1 when it + * cannot be found or read. + */ extern int cgit_print_file(char *path, const char *head, int file_only, int html_escape); + extern void cgit_print_blob(const char *hex, char *path, const char *head, int file_only); #endif // CGIT_UI_BLOB_H diff --git a/source/ui-summary.c b/source/ui-summary.c index 44abc6b..005263a 100644 --- a/source/ui-summary.c +++ b/source/ui-summary.c @@ -71,6 +71,7 @@ void cgit_print_summary(void) void cgit_print_repo_readme(void) { char *filename, *ref; + int err = 0; cgit_print_layout_start(); filename = ctx.repo->readme.items[0].string; @@ -82,7 +83,7 @@ void cgit_print_repo_readme(void) // into safe HTML, so it is escaped rather than served raw. html("
");
 		if (ref) {
-			cgit_print_file(filename, ref, 1, 1);
+			err = cgit_print_file(filename, ref, 1, 1);
 		} else {
 			struct strbuf sb = STRBUF_INIT;
 			if (strbuf_read_file(&sb, filename, 0) >= 0)
@@ -101,7 +102,7 @@ void cgit_print_repo_readme(void)
 		// through unescaped.
 		cgit_open_filter(ctx.repo->about_filter, filename, tree_base.buf, tree_query.buf);
 		if (ref)
-			cgit_print_file(filename, ref, 1, 0);
+			err = cgit_print_file(filename, ref, 1, 0);
 		else
 			html_include(filename);
 		cgit_close_filter(ctx.repo->about_filter);
@@ -109,5 +110,10 @@ void cgit_print_repo_readme(void)
 		strbuf_release(&tree_query);
 	}
 	html("");
+	// A readme past max-blob-size is never read, which would otherwise
+	// leave the about page with nothing on it.
+	if (err == -2)
+		cgit_print_error_page(413, "Content Too Large", "The readme is larger than max-blob-size (%d KB)",
+			ctx.cfg.max_blob_size);
 	cgit_print_layout_end();
 }
diff --git a/tests/t0303-robustness.sh b/tests/t0303-robustness.sh
index 848b03a..d2bf79f 100755
--- a/tests/t0303-robustness.sh
+++ b/tests/t0303-robustness.sh
@@ -755,4 +755,19 @@ test_expect_success SANITY 'a scan entry that cannot be searched is named in ful
 	grep "Unable to stat .*scanperm/locked/objects: Permission denied" err
 '
 
+# A readme past max-blob-size is never read, so the about page says why it
+# has nothing to show.
+test_expect_success 'a readme past max-blob-size is reported on the about page' '
+	test_seq 1 1000 >repos/rob/big-readme &&
+	git -C repos/rob add big-readme &&
+	git -C repos/rob commit -q -m "big readme" &&
+	{
+		echo "max-blob-size=1" &&
+		cat robrc &&
+		echo "repo.readme=:big-readme"
+	} >bigreadmerc &&
+	CGIT_CONFIG="$PWD/bigreadmerc" QUERY_STRING="url=rob/about/" cgit >tmp &&
+	grep "The readme is larger than max-blob-size (1 KB)" tmp
+'
+
 test_done
-- 
cgit