Re: [PATCH] libperf cpumap: Fix argument x range [] exceeds maximum object size
From: Chingbin Li
Date: Fri Feb 13 2026 - 04:37:46 EST
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.
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
> >