From 42adaa11aa0a66645d4cf94488c88660cea00c41 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Mon, 21 Sep 2026 21:34:12 -1000 Subject: Harden the page renderers --- source/ui-shared.c | 187 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 65 deletions(-) (limited to 'source/ui-shared.c') diff --git a/source/ui-shared.c b/source/ui-shared.c index bb786a6..25a84a6 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -27,9 +27,6 @@ #define MIN_TRUNCATE_LEN 15 #define ELLIPSIS_LEN 3 -// Lines of context git itself defaults to, which a link has no reason to name. -#define DEFAULT_DIFF_CONTEXT 3 - // Bounds the breadcrumbs, so that one request cannot turn into an unbounded // row of links. #define MAX_CRUMB_LEVELS 15 @@ -49,7 +46,7 @@ static const char *repo_basename(const char *reponame) len = strlcpy(buf, reponame, sizeof(buf)); if (len >= sizeof(buf)) - die("repo_basename: truncated repository name '%s'", reponame); + die("Repository name too long: %s", reponame); last = len - 1; while (last && buf[last] == '/') buf[last--] = '\0'; @@ -212,7 +209,7 @@ static void emit_diff_args(const char *delim) { if (ctx.qry.difftype) { html(delim); - htmlf("dt=%d", ctx.qry.difftype); + htmlf("dt=%d", (int)ctx.qry.difftype); delim = "&"; } if (ctx.qry.context > 0 && ctx.qry.context != DEFAULT_DIFF_CONTEXT) { @@ -395,9 +392,16 @@ static void add_clone_urls(void (*fn)(const char *), char *urls, char *suffix) static const struct object_id *pinned_oid(void) { static struct object_id oid; + static int resolved, pinned; struct object_id head_oid; struct commit *commit; + // The chrome asks several times per page and the answer cannot change + // within a request. + if (resolved) + return pinned ? &oid : NULL; + resolved = 1; + if (!ctx.repo || !ctx.qry.has_oid || !ctx.qry.oid || !ctx.qry.head) return NULL; if (repo_get_oid(the_repository, ctx.qry.oid, &oid) || @@ -412,6 +416,7 @@ static const struct object_id *pinned_oid(void) oidcpy(&oid, &commit->object.oid); if (oideq(&oid, &head_oid)) return NULL; + pinned = 1; return &oid; } @@ -463,6 +468,7 @@ static int print_branch_option(const struct reference *ref, void *data) { struct branch_option_data *opt = data; const char *name = ref->name; + // The switcher runs on every page, so it is bounded like the refs list. if (ctx.cfg.max_ref_count && opt->count >= ctx.cfg.max_ref_count) return -1; @@ -501,13 +507,15 @@ static void print_header(void) cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1); html(" : "); cgit_summary_link(ctx.repo->name, NULL, NULL, NULL); - } else + } else { html_txt(ctx.cfg.root_title); + } html("\n"); // A repository with no commits has no branches to list, so the - // switcher would be an empty select next to a switch button. - if (ctx.repo && ctx.env.authenticated && !ctx.empty_repo) { + // switcher would be an empty select next to a switch button, and an + // error raised before the head was resolved has nothing to select. + if (ctx.repo && ctx.env.authenticated && !ctx.empty_repo && ctx.qry.head) { const struct object_id *pinned = pinned_oid(); // Only one option may carry selected, and a pinned commit // outranks the branch it was reached from. @@ -577,7 +585,8 @@ static void print_repo_tabs(void) html("