All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v3 01/14] perf stat: Introduce core generic print traversal engine and header stubs
Date: Thu, 16 Jul 2026 04:47:31 +0000	[thread overview]
Message-ID: <20260716044732.431A31F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260716043223.388233-2-irogers@google.com>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:

New issues:
- [High] Crash in `is_basic_shadow_metric` if `mexp->metric_name` is NULL.
- [High] NULL pointer dereferences in metric calculation when `config->aggr_map` is NULL.
- [High] The new `is_basic_shadow_metric` filter erroneously drops all custom user metrics in standard output mode.
- [Medium] The core display traversal driver completely omits `should_skip_zero_counter()` logic, resulting in massive log spam.
- [Low] Manual forward declaration of standard POSIX type `struct timespec` violates musl compatibility guidelines.

Pre-existing issues:
- [High] Uninitialized pointer `unit` is passed to `cb->print_metric()` if `perf_pmu__convert_scale()` fails.
--

--- Patch [1]: [PATCH v3 01/14] perf stat: Introduce core generic print traversal engine and header stubs ---
commit 82eac7a69c1cb36c36fa86107ab3ce1a2fd91c7d
Author: Ian Rogers <irogers@google.com>

perf stat: Introduce core generic print traversal engine and header stubs

This patch introduces the initial infrastructure for decoupling the perf stat
printing API. It declares the struct perf_stat_print_callbacks interface
and the generic traversal driver perf_stat__print_cb() alongside format-agnostic
shared helpers.

> diff --git a/tools/perf/util/stat-print.c b/tools/perf/util/stat-print.c
> new file mode 100644
> index 0000000000000..0fff50dce80be
> --- /dev/null
> +++ b/tools/perf/util/stat-print.c
[ ... ]
> +static bool tool_pmu__is_time_event(const struct perf_stat_config *config,
> +				    const struct evsel *evsel, int *tool_aggr_idx)
> +{
> +	enum tool_pmu_event event = evsel__tool_event(evsel);
> +	int aggr_idx;
> +
> +	if (event != TOOL_PMU__EVENT_DURATION_TIME && event != TOOL_PMU__EVENT_USER_TIME &&
> +	    event != TOOL_PMU__EVENT_SYSTEM_TIME)
> +		return false;
> +
> +	if (config) {
> +		cpu_aggr_map__for_each_idx(aggr_idx, config->aggr_map) {

[Severity: High]
Can this dereference a NULL config->aggr_map?

In perf_stat__print_cb(), there is a fallback path where config->aggr_map is
NULL. It calls perf_stat_print_metrics(..., 0), which calls prepare_metric().
When prepare_metric() invokes tool_pmu__is_time_event(), the macro
cpu_aggr_map__for_each_idx() appears to dereference aggr_map->nr without
checking if the map is NULL.

[ ... ]
> +static int prepare_metric(const struct perf_stat_config *config, const struct metric_expr *mexp,
> +			  struct evsel *evsel, struct expr_parse_ctx *pctx, int aggr_idx)
> +{
[ ... ]
> +		if (!ps || !metric_events[i]->supported) {
> +			val = NAN;
> +			source_count = 0;
> +		} else {
> +			struct perf_stat_aggr *aggr =
> +				&ps->aggr[is_tool_time ? tool_aggr_idx : aggr_idx];
> +
> +			if (aggr->counts.run == 0) {

[Severity: High]
Does this code dereference a NULL pointer when config->aggr_map is NULL?

If we reach this path from the fallback branch in perf_stat__print_cb() where
config->aggr_map is NULL, ps->aggr will also be NULL.

[ ... ]
> +static int calculate_and_print_metric(const struct perf_stat_config *config,
> +				      const struct perf_stat_print_callbacks *cb, void *outer_ctx,
> +				      struct metric_expr *mexp, struct evsel *evsel, int aggr_idx)
> +{
[ ... ]
> +			char *unit;
> +
> +			if (metric_threshold &&
> +			    expr__parse(&threshold, pctx, metric_threshold) == 0 &&
> +			    !isnan(threshold)) {
> +				thresh = fpclassify(threshold) == FP_ZERO ? METRIC_THRESHOLD_GOOD :
> +									    METRIC_THRESHOLD_BAD;
> +			}
> +
> +			if (metric_unit && metric_name) {
> +				if (perf_pmu__convert_scale(metric_unit, &unit, &scale) >= 0)
> +					ratio *= scale;
> +
> +				ret = cb->print_metric(outer_ctx, config, evsel, aggr_idx,
> +						       metric_name, unit, ratio, thresh);

[Severity: High]
This is a pre-existing issue, but does this pass an uninitialized unit pointer
to print_metric() if perf_pmu__convert_scale() fails?

If perf_pmu__convert_scale() returns a negative value, unit will remain
uninitialized. The call to cb->print_metric() sits outside the success check,
so it seems we'll pass whatever happens to be on the stack.

> +			} else {
> +				ret = cb->print_metric(outer_ctx, config, evsel, aggr_idx,
> +						       metric_name ?: (evsel->name ?: ""), NULL,
> +						       ratio, thresh);
> +			}
> +		}
> +	}
> +
> +	expr__ctx_free(pctx);
> +	return ret;
> +}
> +
> +/**
> + * perf_stat_print_metricgroup - Traverse metrics for an event.
> + *
> + * Returns 0 on success, or a negative error code on failure.
> + */
> +static bool is_basic_shadow_metric(const char *name)
> +{
> +	static const char *const basic_metrics[] = {
> +		"insn_per_cycle",   "branch_miss_rate",	      "branch_frequency",
> +		"cycles_frequency", "page_faults_per_second", "migrations_per_second",
> +		"cs_per_second",    "CPUs_utilized",
> +	};
> +	for (size_t i = 0; i < ARRAY_SIZE(basic_metrics); i++) {
> +		if (!strcmp(basic_metrics[i], name))

[Severity: High]
Can this strcmp() trigger a segmentation fault if name is NULL?

In calculate_and_print_metric() just above, metric_name is handled as
potentially NULL. If mexp->metric_name is NULL here, we might crash.

> +			return true;
> +	}
> +	return false;
> +}
> +
> +static int perf_stat_print_metricgroup(const struct perf_stat_config *config,
> +				       const struct perf_stat_print_callbacks *cb, void *outer_ctx,
> +				       struct evsel *evsel, int aggr_idx)
> +{
> +	struct metric_event *me;
> +	struct metric_expr *mexp;
> +	struct rblist *metric_events = &evsel->evlist->metric_events;
> +	int ret;
> +
> +	me = metricgroup__lookup(metric_events, evsel, false);
> +	if (me == NULL)
> +		return 0;
> +
> +	list_for_each_entry(mexp, &me->head, nd) {
> +		if (!config->metric_only &&
> +		    (!evsel->default_metricgroup || evsel->default_show_events)) {
> +			if (!is_basic_shadow_metric(mexp->metric_name))
> +				continue;

[Severity: High]
Does this logic erroneously filter out all custom user metrics?

When a user specifies a custom metric, evsel->default_metricgroup is false.
Unless running in --metric-only mode, the condition evaluates to true, and
is_basic_shadow_metric() will return false for the custom metric, causing the
loop to drop it entirely.

> +		}
> +
> +		ret = calculate_and_print_metric(config, cb, outer_ctx, mexp, evsel, aggr_idx);
> +		if (ret)
> +			return ret;
> +	}
> +	return 0;
> +}
[ ... ]
> +int perf_stat__print_cb(struct evlist *evlist, const struct perf_stat_config *config,
> +			const struct target *target __maybe_unused,
> +			const struct timespec *ts __maybe_unused, int argc __maybe_unused,
> +			const char **argv __maybe_unused,
> +			const struct perf_stat_print_callbacks *cb, void *ctx)
> +{
[ ... ]
> +		if (config->aggr_map) {
> +			cpu_aggr_map__for_each_idx(aggr_idx, config->aggr_map) {
> +				evlist__for_each_entry(evlist, counter) {
[ ... ]
> +					if (cb->print_event) {
> +						double stdev_pct = 0.0;
> +
> +						if (ps && ps->res_stats.n > 1) {
> +							stdev_pct = rel_stddev_stats(
> +								stddev_stats(&ps->res_stats), val);
> +						}
> +						ret = cb->print_event(ctx, config, counter,
> +								      aggr_idx, val, ena, run,
> +								      stdev_pct);

[Severity: Medium]
Will this omission of should_skip_zero_counter() logic result in log spam?

The loop iterates over all counters and unconditionally calls print_event()
for them, even if they have zero counts and shouldn't be printed for this CPU
map, which could break legacy output expectations by printing irrelevant uncore
events.

> +						if (ret)
> +							goto out;
> +					}
[ ... ]
> diff --git a/tools/perf/util/stat-print.h b/tools/perf/util/stat-print.h
> new file mode 100644
> index 0000000000000..a86414f325841
> --- /dev/null
> +++ b/tools/perf/util/stat-print.h
> @@ -0,0 +1,133 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __PERF_STAT_PRINT_H
> +#define __PERF_STAT_PRINT_H
> +
> +#include <linux/types.h>
> +
> +#include "stat.h"
> +
> +#define CNTR_NOT_SUPPORTED "<not supported>"
> +#define CNTR_NOT_COUNTED "<not counted>"
> +
> +struct evlist;
> +struct perf_stat_config;
> +struct target;
> +struct timespec;

[Severity: Low]
Is this manual forward declaration of struct timespec going to cause build
failures on musl libc systems?

According to POSIX compatibility guidelines for musl, standard libc types
should not be forward declared manually. Instead, the appropriate header
should be explicitly included.

> +struct evsel;
> +struct aggr_cpu_id;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260716043223.388233-1-irogers@google.com?part=1

  reply	other threads:[~2026-07-16  4:47 UTC|newest]

Thread overview: 91+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-22 22:33 [RFC PATCH v1 00/14] perf stat: Decouple and modularize metrics/events output printing API Ian Rogers
2026-05-22 22:33 ` [RFC PATCH v1 01/14] perf stat: Introduce core generic print traversal engine and header stubs Ian Rogers
2026-05-22 23:47   ` sashiko-bot
2026-05-22 22:33 ` [RFC PATCH v1 02/14] perf stat: Implement standard console (STD) formatting callbacks Ian Rogers
2026-05-22 22:54   ` sashiko-bot
2026-05-22 22:33 ` [RFC PATCH v1 03/14] perf stat: Extend STD output linter to test basic New API checks Ian Rogers
2026-05-22 22:33 ` [RFC PATCH v1 04/14] perf stat: Extend STD output linter to test core aggregation checks Ian Rogers
2026-05-22 22:33 ` [RFC PATCH v1 05/14] perf stat: Extend STD output linter to test advanced PMU checks Ian Rogers
2026-05-22 22:33 ` [RFC PATCH v1 06/14] perf stat: Extend STD output linter to test metric-only checks Ian Rogers
2026-05-22 22:33 ` [RFC PATCH v1 07/14] perf stat: Implement CSV formatting callbacks Ian Rogers
2026-05-22 23:01   ` sashiko-bot
2026-05-22 22:33 ` [RFC PATCH v1 08/14] perf stat: Extend CSV output linter to test core aggregation checks Ian Rogers
2026-05-22 22:59   ` sashiko-bot
2026-05-22 22:33 ` [RFC PATCH v1 09/14] perf stat: Extend CSV output linter to test advanced PMU and metric-only checks Ian Rogers
2026-05-22 22:48   ` sashiko-bot
2026-05-22 22:33 ` [RFC PATCH v1 10/14] perf stat: Implement streaming JSON formatting callbacks Ian Rogers
2026-05-22 23:02   ` sashiko-bot
2026-05-22 22:33 ` [RFC PATCH v1 11/14] perf stat: Extend JSON output linter to test core aggregation checks Ian Rogers
2026-05-22 22:53   ` sashiko-bot
2026-05-22 22:33 ` [RFC PATCH v1 12/14] perf stat: Extend JSON output linter to test advanced PMU and metric-only checks Ian Rogers
2026-05-22 22:33 ` [RFC PATCH v1 13/14] perf stat: Add --new support to PMU metrics Python validator Ian Rogers
2026-05-22 22:33 ` [RFC PATCH v1 14/14] perf stat: Extend PMU metrics value linter to validate --new outputs Ian Rogers
2026-05-25 23:18 ` [RFC PATCH v2 00/14] perf stat: Decouple and modularize metrics/events output printing API Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 01/14] perf stat: Introduce core generic print traversal engine and header stubs Ian Rogers
2026-05-25 23:38     ` Arnaldo Carvalho de Melo
2026-05-25 23:48       ` Ian Rogers
2026-05-26  0:20         ` Arnaldo Carvalho de Melo
2026-05-25 23:18   ` [RFC PATCH v2 02/14] perf stat: Implement standard console (STD) formatting callbacks Ian Rogers
2026-05-25 23:49     ` Arnaldo Carvalho de Melo
2026-05-26  0:09       ` Ian Rogers
2026-05-25 23:53     ` sashiko-bot
2026-05-25 23:18   ` [RFC PATCH v2 03/14] perf stat: Extend STD output linter to test basic New API checks Ian Rogers
2026-05-25 23:39     ` Arnaldo Carvalho de Melo
2026-05-25 23:18   ` [RFC PATCH v2 04/14] perf stat: Extend STD output linter to test core aggregation checks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 05/14] perf stat: Extend STD output linter to test advanced PMU checks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 06/14] perf stat: Extend STD output linter to test metric-only checks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 07/14] perf stat: Implement CSV formatting callbacks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 08/14] perf stat: Extend CSV output linter to test core aggregation checks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 09/14] perf stat: Extend CSV output linter to test advanced PMU and metric-only checks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 10/14] perf stat: Implement streaming JSON formatting callbacks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 11/14] perf stat: Extend JSON output linter to test core aggregation checks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 12/14] perf stat: Extend JSON output linter to test advanced PMU and metric-only checks Ian Rogers
2026-05-25 23:18   ` [RFC PATCH v2 13/14] perf stat: Add --new support to PMU metrics Python validator Ian Rogers
2026-05-25 23:19   ` [RFC PATCH v2 14/14] perf stat: Extend PMU metrics value linter to validate --new outputs Ian Rogers
2026-05-25 23:53     ` sashiko-bot
2026-06-05 18:02   ` [RFC PATCH v2 00/14] perf stat: Decouple and modularize metrics/events output printing API Chun-Tse Shao
2026-07-16  4:32   ` [PATCH v3 00/14] perf stat: Decouple printing API and introduce streaming zero-allocation printers Ian Rogers
2026-07-16  4:32     ` [PATCH v3 01/14] perf stat: Introduce core generic print traversal engine and header stubs Ian Rogers
2026-07-16  4:47       ` sashiko-bot [this message]
2026-07-16  4:32     ` [PATCH v3 02/14] perf stat: Implement standard console (STD) formatting callbacks Ian Rogers
2026-07-16  4:44       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 03/14] perf stat: Extend STD output linter to test basic New API checks Ian Rogers
2026-07-16  4:42       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 04/14] perf stat: Extend STD output linter to test core aggregation checks Ian Rogers
2026-07-16  4:38       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 05/14] perf stat: Extend STD output linter to test advanced PMU checks Ian Rogers
2026-07-16  4:43       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 06/14] perf stat: Extend STD output linter to test metric-only checks Ian Rogers
2026-07-16  4:32     ` [PATCH v3 07/14] perf stat: Implement CSV formatting callbacks Ian Rogers
2026-07-16  4:43       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 08/14] perf stat: Extend CSV output linter to test core aggregation checks Ian Rogers
2026-07-16  4:32     ` [PATCH v3 09/14] perf stat: Extend CSV output linter to test advanced PMU and metric-only checks Ian Rogers
2026-07-16  4:32     ` [PATCH v3 10/14] perf stat: Implement streaming JSON formatting callbacks Ian Rogers
2026-07-16  4:46       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 11/14] perf stat: Extend JSON output linter to test core aggregation checks Ian Rogers
2026-07-16  4:42       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 12/14] perf stat: Extend JSON output linter to test advanced PMU and metric-only checks Ian Rogers
2026-07-16  4:32     ` [PATCH v3 13/14] perf stat: Add --new support to PMU metrics Python validator Ian Rogers
2026-07-16  4:52       ` sashiko-bot
2026-07-16  4:32     ` [PATCH v3 14/14] perf stat: Extend PMU metrics value linter to validate --new outputs Ian Rogers
2026-07-16  4:49       ` sashiko-bot
2026-07-16  7:02     ` [PATCH v4 00/14] perf stat: Decouple and modularize display formatting Ian Rogers
2026-07-16  7:02       ` [PATCH v4 01/14] perf stat: Introduce core generic print traversal engine and header stubs Ian Rogers
2026-07-16  7:16         ` sashiko-bot
2026-07-16  7:02       ` [PATCH v4 02/14] perf stat: Implement standard console (STD) formatting callbacks Ian Rogers
2026-07-16  7:24         ` sashiko-bot
2026-07-16  7:02       ` [PATCH v4 03/14] perf stat: Extend STD output linter to test basic New API checks Ian Rogers
2026-07-16  7:02       ` [PATCH v4 04/14] perf stat: Extend STD output linter to test core aggregation checks Ian Rogers
2026-07-16  7:02       ` [PATCH v4 05/14] perf stat: Extend STD output linter to test advanced PMU checks Ian Rogers
2026-07-16  7:02       ` [PATCH v4 06/14] perf stat: Extend STD output linter to test metric-only checks Ian Rogers
2026-07-16  7:02       ` [PATCH v4 07/14] perf stat: Implement CSV formatting callbacks Ian Rogers
2026-07-16  7:11         ` sashiko-bot
2026-07-16  7:02       ` [PATCH v4 08/14] perf stat: Extend CSV output linter to test core aggregation checks Ian Rogers
2026-07-16  7:02       ` [PATCH v4 09/14] perf stat: Extend CSV output linter to test advanced PMU and metric-only checks Ian Rogers
2026-07-16  7:02       ` [PATCH v4 10/14] perf stat: Implement streaming JSON formatting callbacks Ian Rogers
2026-07-16  7:19         ` sashiko-bot
2026-07-16  7:03       ` [PATCH v4 11/14] perf stat: Extend JSON output linter to test core aggregation checks Ian Rogers
2026-07-16  7:03       ` [PATCH v4 12/14] perf stat: Extend JSON output linter to test advanced PMU and metric-only checks Ian Rogers
2026-07-16  7:03       ` [PATCH v4 13/14] perf stat: Add --new support to PMU metrics Python validator Ian Rogers
2026-07-16  7:03       ` [PATCH v4 14/14] perf stat: Extend PMU metrics value linter to validate --new outputs Ian Rogers
2026-07-16  7:16         ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260716044732.431A31F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=irogers@google.com \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.