Re: [PATCH] libperf cpumap: Fix argument x range [] exceeds maximum object size
From: Ian Rogers
Date: Tue Feb 24 2026 - 12:58:43 EST
On Fri, Feb 13, 2026 at 1:34 AM Chingbin Li <liqb365@xxxxxxx> wrote:
>
> Hi, Ian:
>
> -------------------------------------------------------------------------------------
> About whether this issue is unique to the RISC-V architecture, my test result is:
>
> Machine / OS / Whether it occurred
> AMD9950x / Ubuntu 24.04 / No
> qemu-system-x86_64 / Ubuntu 24.04 / No
> qemu-system-riscv64 / Ubuntu 24.04 / Yes
>
> So I haven't observed the same issue on computers other than riscv64 yet.
>
> -------------------------------------------------------------------------------------
> I think there are several ways to fix this issue.
>
> a. Add the volatile qualifier to the tmp_len variable.
> b. Use #pragma to ignore the warning.
> c. Change the type of the tmp_len variable to size_t.
> However, After trying it out, changing the type alone does not fix this issue;
> a numerical range check also needs to be added.
>
> These methods seem to have some shortcomings.
>
> My current thought is that adding a numerical range check seems to be a more appropriate solution.
> It can effectively resolve the issue even without changing the type of tmp_len.
>
> diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c
> index 4160e7d2e120f..e0407796fcd9d 100644
> --- a/tools/lib/perf/cpumap.c
> @@ -413,6 +413,8 @@ int perf_cpu_map__merge(struct perf_cpu_map **orig, struct p
> +++ b/tools/lib/perf/cpumap.c
> @@ -413,6 +413,8 @@ int perf_cpu_map__merge(struct perf_cpu_map **orig, struct perf_cpu_map *other)
> int tmp_len;
> int i, j, k;
> struct perf_cpu_map *merged;
> + int orig_nr = __perf_cpu_map__nr(*orig);
> + int other_nr = __perf_cpu_map__nr(other);
>
> if (perf_cpu_map__is_subset(*orig, other))
> return 0;
> @@ -422,7 +424,11 @@ int perf_cpu_map__merge(struct perf_cpu_map **orig, struct perf_cpu_map *other)
> return 0;
> }
>
> - tmp_len = __perf_cpu_map__nr(*orig) + __perf_cpu_map__nr(other);
> + if (orig_nr < 0 || other_nr < 0 || orig_nr + other_nr > INT_MAX) {
> + return -EINVAL;
> + }
> + tmp_len = orig_nr + other_nr;
> tmp_cpus = malloc(tmp_len * sizeof(struct perf_cpu));
> if (!tmp_cpus)
> return -ENOMEM;
>
> This method has good compatibility while keeping `tmp_len` and other variables used for comparison the same type.
> If you agree with this idea, I will submit it as a v2 patch.
>
> -------------------------------------------------------------------------------------
> I agree that the nr field type should be changed to size_t.
> I tried making the modification. It seems that after this modification,
> there will be comparisons between `int` and `size_t` variables,
> which will require some type casting.
It'd be great to have this clean up, int to size_t and making the nr
in the cpumap unsigned. I'm less keen on the volatile or range checks
to avoid the "-Werror=alloc-size-larger-than=". There is a
MAX_NR_CPUS which may be marginally better than INT_MAX. The sign
comparison is somewhat of a pain :-(
Thanks,
Ian
> Thanks,
> Chingbin
>
> On Thu, Feb 12, 2026 at 10:24:12AM -0800, Ian Rogers wrote:
> > On Wed, Feb 11, 2026 at 6:54 PM Chingbin Li <liqb365@xxxxxxx> wrote:
> > >
> > > On RISC-V 64-bit Ubuntu 24.04 Server (Running on QEMU), the following error might occur when compiling perf:
> > >
> > > cpumap.c: In function ‘perf_cpu_map__merge’:
> > > cpumap.c:429:20: error: argument 1 range [18446744069414584320, 18446744073709551614] exceeds maximum object size 9223372036854775807 [-Werror=alloc-size-larger-than=]
> > > 429 | tmp_cpus = malloc(tmp_len * sizeof(struct perf_cpu));
> > > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > In file included from cpumap.c:4:
> > > /usr/include/stdlib.h:672:14: note: in a call to allocation function ‘malloc’ declared here
> > > 672 | extern void *malloc (size_t __size) __THROW __attribute_malloc__
> > > | ^~~~~~
> > > cc1: all warnings being treated as errors
> > >
> > > We use the volatile qualifier to prevent unnecessary errors caused by the compiler's constant propagation.
> >
> > This shouldn't be a RISC-V specific problem.Does changing tmp_len to a
> > size_t fix it? __perf_cpu_map__nr and perf_cpu_map__nr should
> > probably both return a size_t too, and the type of nr in struct
> > perf_cpu_map should not be signed.
> >
> > Thanks,
> > Ian
> >
> > > ---
> > > tools/lib/perf/cpumap.c | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c
> > > index 4160e7d2e120..ccf473994111 100644
> > > --- a/tools/lib/perf/cpumap.c
> > > +++ b/tools/lib/perf/cpumap.c
> > > @@ -410,7 +410,7 @@ bool perf_cpu_map__is_subset(const struct perf_cpu_map *a, const struct perf_cpu
> > > int perf_cpu_map__merge(struct perf_cpu_map **orig, struct perf_cpu_map *other)
> > > {
> > > struct perf_cpu *tmp_cpus;
> > > - int tmp_len;
> > > + volatile int tmp_len;
> > > int i, j, k;
> > > struct perf_cpu_map *merged;
> > >
> > > --
> > > 2.43.0
> > >
>