[PATCH] perf config: Use va_copy() in perf_config_scan_cb() to avoid va_list reuse

From: Adrián García Casado

Date: Mon Nov 09 2026 - 09:43:30 EST


perf_config() iterates through both the system-wide config file
(/etc/perfconfig) and the user config file (~/.perfconfig) so that user
settings override system defaults.

If a configuration key queried via perf_config_scan() appears more than
once (for example, in both /etc/perfconfig and ~/.perfconfig, or
duplicated within the same file), perf_config_scan_cb() invokes
vsscanf(value, d->fmt, d->args) multiple times on the same va_list
without reinitializing it.

Because vsscanf() consumes arguments from 'd->args' via va_arg(), a
subsequent match reads past the end of the argument list into
uninitialized stack memory.

Copy 'd->args' with va_copy() before calling vsscanf() in
perf_config_scan_cb() so that multiple matches safely overwrite the
destination variables with the latest value.

Signed-off-by: Adrián García Casado <adriangarciacasado42@xxxxxxxxx>
---
tools/perf/util/config.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 287401f159e66..f567cc338ca9d 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -1091,8 +1091,13 @@ static int perf_config_scan_cb(const char *var, const char *value, void *data)
{
struct perf_config_scan_data *d = data;

- if (!strcmp(var, d->name))
- d->ret = vsscanf(value, d->fmt, d->args);
+ if (!strcmp(var, d->name)) {
+ va_list args;
+
+ va_copy(args, d->args);
+ d->ret = vsscanf(value, d->fmt, args);
+ va_end(args);
+ }

return 0;
}
--
2.39.5