From 3ea188e2bb5e7994645a03e19bf613369bc20585 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Sat, 8 Aug 2026 12:49:45 -1000 Subject: Expand `module-link` placeholders outside printf --- source/ui-shared.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/ui-shared.c b/source/ui-shared.c index 1b65a7f..125a235 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -616,6 +616,39 @@ static struct string_list_item *lookup_path(struct string_list *list, return NULL; } +/* + * Expand the %s placeholders in a module-link template and emit the result as + * an attribute value. The template is never handed to printf: a repository can + * supply its own through a repo-local cgitrc, and a surplus conversion would + * then read past the argument list. + */ +static void html_module_link(const char *tmpl, const char **args, int nargs) +{ + struct strbuf sb = STRBUF_INIT; + int used = 0; + + while (*tmpl) { + if (*tmpl != '%') { + strbuf_addch(&sb, *tmpl++); + continue; + } + tmpl++; + if (*tmpl == '%') { + strbuf_addch(&sb, '%'); + tmpl++; + } else if (*tmpl == 's' && used < nargs) { + strbuf_addstr(&sb, args[used++]); + tmpl++; + } else { + // Anything else is not a placeholder this template can + // fill, so keep it verbatim rather than dropping it. + strbuf_addch(&sb, '%'); + } + } + html_attr(sb.buf); + strbuf_release(&sb); +} + void cgit_submodule_link(const char *class, char *path, const char *rev) { struct string_list *list; @@ -641,14 +674,19 @@ void cgit_submodule_link(const char *class, char *path, const char *rev) htmlf("class='%s' ", class); html("href='"); if (item) { - html_attrf(item->util, rev); + // A per-path template names only the submodule commit. + const char *args[] = { rev }; + html_module_link(item->util, args, 1); } else { + const char *args[2]; dir = strrchr(path, '/'); if (dir) dir++; else dir = path; - html_attrf(ctx.repo->module_link, dir, rev); + args[0] = dir; + args[1] = rev; + html_module_link(ctx.repo->module_link, args, 2); } html("'>"); html_txt(path); -- cgit v2.8.0