Re: [PATCH 10/11] perf tools: Use scnprintf() in build_id__snprintf() and hwmon read_events()
From: Ian Rogers
Date: Wed Jun 10 2026 - 13:09:59 EST
On Wed, Jun 10, 2026 at 9:53 AM Arnaldo Carvalho de Melo
<acme@xxxxxxxxxx> wrote:
>
> From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
>
> build_id__snprintf() and hwmon_pmu__read_events() accumulate formatted
> output via snprintf(), which returns the would-have-been-written count
> on truncation. In build_id__snprintf(), this inflates the return
> value beyond the buffer size. In hwmon_pmu__read_events(), len
> overshoots out_buf_len and the next 'out_buf_len - len' underflows.
>
> Switch both to scnprintf() which returns actual bytes written.
>
> In build_id__snprintf(), also tighten the loop guard from
> 'offs < bf_size' to 'offs + 1 < bf_size': since scnprintf() returns
> at most size-1, offs never reaches bf_size, and the original condition
> would spin doing zero-byte writes once the buffer fills.
Reviewed-by: Ian Rogers <irogers@xxxxxxxxxx>
Thanks,
Ian
> Fixes: fccaaf6fbbc59910 ("perf build-id: Change sprintf functions to snprintf")
> Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs")
> Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
> Cc: Ian Rogers <irogers@xxxxxxxxxx>
> Assisted-by: Claude Opus 4.6 <noreply@xxxxxxxxxxxxx>
> Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
> ---
> tools/perf/util/build-id.c | 7 +++++--
> tools/perf/util/hwmon_pmu.c | 12 ++++++------
> 2 files changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index 8c0a9ae932aa5798..eb95ab90f9741d5f 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -93,8 +93,11 @@ int build_id__snprintf(const struct build_id *build_id, char *bf, size_t bf_size
> return 0;
> }
>
> - for (size_t i = 0; i < build_id->size && offs < bf_size; ++i)
> - offs += snprintf(bf + offs, bf_size - offs, "%02x", build_id->data[i]);
> + if (bf_size > 0)
> + bf[0] = '\0';
> +
> + for (size_t i = 0; i < build_id->size && offs + 1 < bf_size; ++i)
> + offs += scnprintf(bf + offs, bf_size - offs, "%02x", build_id->data[i]);
>
> return offs;
> }
> diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c
> index fb3ffa8d32ad2a93..dbf6a71af47f9a42 100644
> --- a/tools/perf/util/hwmon_pmu.c
> +++ b/tools/perf/util/hwmon_pmu.c
> @@ -442,12 +442,12 @@ static size_t hwmon_pmu__describe_items(struct hwmon_pmu *hwm, char *out_buf, si
>
> buf[read_len] = '\0';
> val = strtoll(buf, /*endptr=*/NULL, 10);
> - len += snprintf(out_buf + len, out_buf_len - len, "%s%s%s=%g%s",
> - len == 0 ? " " : ", ",
> - hwmon_item_strs[bit],
> - is_alarm ? "_alarm" : "",
> - (double)val / 1000.0,
> - hwmon_units[key.type]);
> + len += scnprintf(out_buf + len, out_buf_len - len, "%s%s%s=%g%s",
> + len == 0 ? " " : ", ",
> + hwmon_item_strs[bit],
> + is_alarm ? "_alarm" : "",
> + (double)val / 1000.0,
> + hwmon_units[key.type]);
> }
> close(fd);
> }
> --
> 2.54.0
>