From 596db3ef86844617565a0b4b4ce8358fe6537d87 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Tue, 29 Oct 2024 10:50:27 +0100 Subject: [PATCH] BUG/MINOR: trace: stop rewriting argv with -dt When using trace with -dt, the trace_parse_cmd() function is doing a strtok which write \0 into the argv string. When using the mworker mode, and reloading, argv was modified and the trace won't work anymore because the first : is replaced by a '\0'. This patch fixes the issue by allocating a temporary string so we don't modify the source string directly. It also replace strtok by its reentrant version strtok_r. Must be backported as far as 2.9. --- include/haproxy/trace.h | 2 +- src/trace.c | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/haproxy/trace.h b/include/haproxy/trace.h index f6749160ce..ce94289154 100644 --- a/include/haproxy/trace.h +++ b/include/haproxy/trace.h @@ -190,7 +190,7 @@ void trace_no_cb(enum trace_level level, uint64_t mask, const struct trace_sourc void trace_register_source(struct trace_source *source); -int trace_parse_cmd(char *arg, char **errmsg); +int trace_parse_cmd(const char *arg_src, char **errmsg); /* return a single char to describe a trace state */ static inline char trace_state_char(enum trace_state st) diff --git a/src/trace.c b/src/trace.c index 95ec6aa2e5..cc49ed98b1 100644 --- a/src/trace.c +++ b/src/trace.c @@ -966,11 +966,22 @@ void _trace_parse_cmd(struct trace_source *src, int level, int verbosity) * * Returns 0 on success else non-zero. */ -int trace_parse_cmd(char *arg, char **errmsg) +int trace_parse_cmd(const char *arg_src, char **errmsg) { char *str; + char *arg, *oarg; + char *saveptr; - if (!arg) { + if (arg_src) { + /* keep a copy of the ptr for strtok */ + oarg = arg = strdup(arg_src); + if (!arg) { + memprintf(errmsg, "Can't allocate !"); + return 1; + } + } + + if (!arg_src) { /* No trace specification, activate all sources on error level. */ struct trace_source *src = NULL; @@ -979,7 +990,7 @@ int trace_parse_cmd(char *arg, char **errmsg) return 0; } - while ((str = strtok(arg, ","))) { + while ((str = strtok_r(arg, ",", &saveptr))) { struct trace_source *src = NULL; char *field, *name; char *sep; @@ -1000,6 +1011,7 @@ int trace_parse_cmd(char *arg, char **errmsg) src = trace_find_source(name); if (!src) { memprintf(errmsg, "unknown trace source '%s'", name); + ha_free(&oarg); return 1; } } @@ -1022,6 +1034,7 @@ int trace_parse_cmd(char *arg, char **errmsg) level = trace_parse_level(field); if (level < 0) { memprintf(errmsg, "no such trace level '%s', available levels are 'error', 'user', 'proto', 'state', 'data', and 'developer'", field); + ha_free(&oarg); return 1; } } @@ -1033,6 +1046,7 @@ int trace_parse_cmd(char *arg, char **errmsg) field = str; if (strchr(field, ':')) { memprintf(errmsg, "too many double-colon separators in trace definition"); + ha_free(&oarg); return 1; } @@ -1049,6 +1063,7 @@ int trace_parse_cmd(char *arg, char **errmsg) memprintf(errmsg, "%s, %s'%s'", *errmsg, (nd + 1)->name ? "" : "and ", nd->name); } + ha_free(&oarg); return 1; } @@ -1064,7 +1079,7 @@ int trace_parse_cmd(char *arg, char **errmsg) /* Reset arg to NULL for strtok. */ arg = NULL; } - + ha_free(&oarg); return 0; }