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-log.c | 97 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 26 deletions(-) (limited to 'source/ui-log.c') diff --git a/source/ui-log.c b/source/ui-log.c index 316df75..86cb756 100644 --- a/source/ui-log.c +++ b/source/ui-log.c @@ -176,6 +176,9 @@ static void wrap_subject(struct commitinfo *info, struct strbuf *msg) --cut; if (!cut) cut = ctx.cfg.max_msg_len - strlen(wrap_symbol); + // A cut inside a multibyte character would leave both halves invalid. + while (cut > 0 && (info->subject[cut] & 0xC0) == 0x80) + --cut; strbuf_add(msg, info->subject + cut, subject_len - cut); strbuf_trim(msg); @@ -244,7 +247,7 @@ static void print_commit(struct commit *commit, struct rev_info *revs) oid_to_hex(&commit->object.oid), ctx.qry.vpath); cgit_print_commit_decorations(commit); html(""); - cgit_open_filter(ctx.repo->email_filter, info->author_email, "log"); + cgit_open_filter(ctx.repo->email_filter, info->author_email ? info->author_email : "", "log"); html_txt(info->author); cgit_close_filter(ctx.repo->email_filter); @@ -286,8 +289,9 @@ static void print_commit(struct commit *commit, struct rev_info *revs) int msg_lines = ctx.qry.showmsg ? line_count(msgbuf.buf) : 0; print_graph_padding(revs, &graphbuf, msg_lines); - } else + } else { html(""); + } // Either way one cell is already on the row, so the message // spans the remaining columns. @@ -317,6 +321,27 @@ static const char *disambiguate_ref(const char *ref, int *must_free_result) return ref; } +/* + * A range token is one revision, or two joined by two or three dots, and each + * side has to pass cgit_valid_rev. An empty side means HEAD to git. + */ +static int valid_range_token(const char *arg) +{ + const char *dots = strstr(arg, ".."); + char *left; + int ok; + + if (!dots) + return cgit_valid_rev(arg); + left = xstrndup(arg, dots - arg); + dots += 2; + if (*dots == '.') + dots++; + ok = (!*left || cgit_valid_rev(left)) && (!*dots || cgit_valid_rev(dots)); + free(left); + return ok; +} + static char *next_token(char **src) { char *token; @@ -348,7 +373,7 @@ static void print_pager(struct rev_info *revs, int ofs, int cnt) struct commit *more = get_revision(revs); html("\n"); - // A single page needs no pager, and an empty list is just noise. + // A single page needs no pager, and an empty list has nothing to page. if (ofs <= 0 && !more) return; html("