From 6bec3fbe6fb2eb5f9c74ff27ca894dd34c4d7c5a 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. (cherry picked from commit 596db3ef86844617565a0b4b4ce8358fe6537d87) Signed-off-by: Christopher Faulet --- 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 703ac8d..7c601fe 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 b8a1397..8f8d072 100644 --- a/src/trace.c +++ b/src/trace.c @@ -813,11 +813,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_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) { + if (!arg_src) { /* No trace specification, activate all sources on error level. */ struct trace_source *src = NULL; @@ -826,7 +837,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; @@ -847,6 +858,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; } } @@ -869,6 +881,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; } } @@ -880,6 +893,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; } @@ -896,6 +910,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; } @@ -911,7 +926,7 @@ int trace_parse_cmd(char *arg, char **errmsg) /* Reset arg to NULL for strtok. */ arg = NULL; } - + ha_free(&oarg); return 0; } -- 1.7.10.4