From: Derrick Stolee via GitGitGadget Date: Tue, 25 Aug 2026 18:56:19 GMT Subject: [PATCH v2 5/7] trace2: remove use of xstrfmt() Message-ID: <7f0bb405ad380fd35ae6381961ac667fd7e5dfd9.1787684181.git.gitgitgadget@gmail.com> In-Reply-To: From: Derrick Stolee We continue removing the possibility of a die() in the trace2 API by banning xstrfmt(), which calls die() during a failure to format. Instead of allowing a die(), perform a soft failure by failing to output the trace2 data when such a failure occurs. This requires carefully concatenating strings using memcpy() to construct redacted data to avoid copying password information in traced URLs. Signed-off-by: Derrick Stolee --- banned-die.h | 3 +++ trace2.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/banned-die.h b/banned-die.h index cb2eed75cd..14aecfdc7a 100644 --- a/banned-die.h +++ b/banned-die.h @@ -17,6 +17,9 @@ #undef xstrdup #define xstrdup(str) BANNED(xstrdup) +#undef xstrfmt +#define xstrfmt(...) BANNED(xstrfmt) + #undef ALLOC_ARRAY #define ALLOC_ARRAY(x, alloc) BANNED(ALLOC_ARRAY) diff --git a/trace2.c b/trace2.c index 7044276435..c37f783fa0 100644 --- a/trace2.c +++ b/trace2.c @@ -260,7 +260,10 @@ int trace2_is_enabled(void) static const char *redact_arg(const char *arg) { const char *p, *colon; + const char *redact = ":"; + char *redacted; size_t at; + size_t prefix_len, suffix_len, redacted_len, redact_len; if (!trace2_redact || (!skip_prefix(arg, "https://", &p) && @@ -275,7 +278,25 @@ static const char *redact_arg(const char *arg) if (!colon) return arg; - return xstrfmt("%.*s:%s", (int)(colon - arg), arg, p + at); + redact_len = strlen(redact); + prefix_len = colon - arg; + suffix_len = strlen(p + at); + + if (unsigned_add_overflows(prefix_len, suffix_len) || + unsigned_add_overflows(prefix_len + suffix_len, redact_len)) + return NULL; + + redacted_len = prefix_len + suffix_len + redact_len; + + redacted = malloc(redacted_len); + if (!redacted) + return NULL; + + memcpy(redacted, arg, prefix_len); + memcpy(redacted + prefix_len, redact, redact_len - 1); + memcpy(redacted + prefix_len + redact_len - 1, p + at, + suffix_len + 1); + return redacted; } /* @@ -300,6 +321,8 @@ static const char **redact_argv(const char **argv) if (!argv[i]) return argv; + if (!redacted) + return NULL; for (j = 0; argv[j]; j++) ; /* keep counting */ @@ -316,7 +339,14 @@ static const char **redact_argv(const char **argv) ret[i] = redacted; for (++i; argv[i]; i++) { redacted = redact_arg(argv[i]); - ret[i] = redacted ? redacted : argv[i]; + if (!redacted) { + for (j = 0; j < i; j++) + if (ret[j] != argv[j]) + free((void *)ret[j]); + free(ret); + return NULL; + } + ret[i] = redacted; } return ret; -- gitgitgadget