From 1be85369f36458fe9a2f85ca63285367f94e6172 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Fri, 16 Oct 2026 06:26:24 -1000 Subject: Share the max-blob-size check and its refusal Five copies of the test and four of the error page had to agree by hand. The new check pins the four refusals, which no test covered. --- source/shared.c | 9 ++++++--- source/shared.h | 7 +++++++ source/ui-blame.c | 5 ++--- source/ui-blob.c | 17 ++++------------- source/ui-plain.c | 7 ++----- source/ui-shared.c | 6 ++++++ source/ui-shared.h | 5 +++++ source/ui-tree.c | 6 +++--- 8 files changed, 35 insertions(+), 27 deletions(-) (limited to 'source') diff --git a/source/shared.c b/source/shared.c index 9065693..3191742 100644 --- a/source/shared.c +++ b/source/shared.c @@ -410,9 +410,7 @@ int cgit_diff_files(const struct object_id *old_oid, const struct object_id *new *old_size = old_bytes; *new_size = new_bytes; - if (ctx.cfg.max_blob_size && - (old_bytes / 1024 > (unsigned long)ctx.cfg.max_blob_size || - new_bytes / 1024 > (unsigned long)ctx.cfg.max_blob_size)) { + if (cgit_blob_too_large(old_bytes) || cgit_blob_too_large(new_bytes)) { *binary = 1; return 0; } @@ -450,6 +448,11 @@ int cgit_diff_files(const struct object_id *old_oid, const struct object_id *new return 0; } +int cgit_blob_too_large(unsigned long size) +{ + return ctx.cfg.max_blob_size && size / 1024 > (unsigned long)ctx.cfg.max_blob_size; +} + void cgit_diff_limit_path(struct diff_options *opt, const char *prefix) { struct pathspec_item *item; diff --git a/source/shared.h b/source/shared.h index 46324a1..df18772 100644 --- a/source/shared.h +++ b/source/shared.h @@ -65,6 +65,13 @@ extern int cgit_diff_files(const struct object_id *old_oid, const struct object_ unsigned long *old_size, unsigned long *new_size, int *binary, int context, int ignorews, linediff_fn fn); +/* + * Whether a blob of size bytes is past max-blob-size. Callers ask before + * reading the object, so a huge blob stays out of memory rather than being + * noticed once it is already there. + */ +extern int cgit_blob_too_large(unsigned long size); + /* * Limit a diff to the paths below prefix, which is taken literally. */ diff --git a/source/ui-blame.c b/source/ui-blame.c index 9395098..f3d58c0 100644 --- a/source/ui-blame.c +++ b/source/ui-blame.c @@ -274,9 +274,8 @@ static void print_blame_page(const struct object_id *oid, const char *path, cgit_print_error_page(404, "Not Found", "Bad object id: %s", oid_to_hex(oid)); return; } - if (ctx.cfg.max_blob_size && size / 1024 > (unsigned long)ctx.cfg.max_blob_size) { - cgit_print_error_page(413, "Content Too Large", "Blob size (%lu KB) exceeds the limit (%d KB)", - size / 1024, ctx.cfg.max_blob_size); + if (cgit_blob_too_large(size)) { + cgit_print_blob_too_large(size); return; } diff --git a/source/ui-blob.c b/source/ui-blob.c index 3c3ba71..f7047c7 100644 --- a/source/ui-blob.c +++ b/source/ui-blob.c @@ -11,6 +11,7 @@ #include "cgit.h" #include "html.h" +#include "shared.h" #include "ui-blob.h" #include "ui-shared.h" @@ -94,15 +95,6 @@ static int find_path_oid(struct object_id *oid, char *path, int file_only) return walk.found_path; } -/* - * Callers ask before reading the object, so a huge blob stays out of - * memory rather than being noticed once already there. - */ -static int over_size_limit(unsigned long size) -{ - return ctx.cfg.max_blob_size && size / 1024 > (unsigned long)ctx.cfg.max_blob_size; -} - int cgit_ref_path_exists(const char *path, const char *ref, int file_only) { struct object_id oid; @@ -139,7 +131,7 @@ int cgit_print_file(char *path, const char *head, int file_only, int html_escape } if (type == OBJ_BAD) return -1; - if (over_size_limit(size)) + if (cgit_blob_too_large(size)) return -1; buf = odb_read_object(the_repository->objects, &oid, &type, &size); if (!buf) @@ -210,9 +202,8 @@ void cgit_print_blob(const char *hex, char *path, const char *head, int file_onl return; } - if (over_size_limit(size)) { - cgit_print_error_page(413, "Content Too Large", "Blob size (%lu KB) exceeds the limit (%d KB)", - size / 1024, ctx.cfg.max_blob_size); + if (cgit_blob_too_large(size)) { + cgit_print_blob_too_large(size); return; } diff --git a/source/ui-plain.c b/source/ui-plain.c index 2463cfc..136e1f4 100644 --- a/source/ui-plain.c +++ b/source/ui-plain.c @@ -58,11 +58,8 @@ static void print_object(const struct object_id *oid, const char *path) return; } - // The limit counts kilobytes and is checked before the read, so a huge - // blob is kept out of memory rather than noticed once it is there. - if (ctx.cfg.max_blob_size && size / 1024 > (unsigned long)ctx.cfg.max_blob_size) { - cgit_print_error_page(413, "Content Too Large", "Blob size (%lu KB) exceeds the limit (%d KB)", - size / 1024, ctx.cfg.max_blob_size); + if (cgit_blob_too_large(size)) { + cgit_print_blob_too_large(size); return; } diff --git a/source/ui-shared.c b/source/ui-shared.c index b793f74..fd9cd20 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -1625,6 +1625,12 @@ void cgit_vprint_error_page(int code, const char *msg, const char *fmt, va_list cgit_print_layout_end(); } +void cgit_print_blob_too_large(unsigned long size) +{ + cgit_print_error_page(413, "Content Too Large", "Blob size (%lu KB) exceeds the limit (%d KB)", + size / 1024, ctx.cfg.max_blob_size); +} + void cgit_print_layout_start(void) { cgit_print_http_headers(); diff --git a/source/ui-shared.h b/source/ui-shared.h index c4b96a9..93cc9d2 100644 --- a/source/ui-shared.h +++ b/source/ui-shared.h @@ -97,6 +97,11 @@ extern void cgit_print_docend(void); __attribute__((format (printf,3,4))) extern void cgit_print_error_page(int code, const char *msg, const char *fmt, ...); extern void cgit_vprint_error_page(int code, const char *msg, const char *fmt, va_list ap); + +/* + * Answer with the error page for a blob of size bytes past max-blob-size. + */ +extern void cgit_print_blob_too_large(unsigned long size); extern void cgit_print_pageheader(void); extern void cgit_print_filemode(unsigned short mode); extern void cgit_print_snapshot_links(const struct cgit_repo *repo, const char *ref, diff --git a/source/ui-tree.c b/source/ui-tree.c index 3e2fb5e..d023502 100644 --- a/source/ui-tree.c +++ b/source/ui-tree.c @@ -13,6 +13,7 @@ #include "cgit.h" #include "filter.h" #include "html.h" +#include "shared.h" #include "ui-shared.h" #include "ui-tree.h" @@ -175,9 +176,8 @@ static bool print_object(const struct object_id *oid, const char *path, return false; } - if (ctx.cfg.max_blob_size && size / 1024 > (unsigned long)ctx.cfg.max_blob_size) { - cgit_print_error_page(413, "Content Too Large", "Blob size (%lu KB) exceeds the limit (%d KB)", - size / 1024, ctx.cfg.max_blob_size); + if (cgit_blob_too_large(size)) { + cgit_print_blob_too_large(size); return false; } -- cgit