Hi,

There was a recent bug filed in Fedora Rawhide that libpfm fails to build with 
GCC 12 (https://bugzilla.redhat.com/show_bug.cgi?id=2045823).  GCC is doing 
some additional analysis of the code and doesn't like pointers to be used after 
they are possibly freed:

gcc -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches 
-pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 
-Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 
-fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  
-mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection 
-fcf-protection -O2 -flto=auto -ffat-lto-objects -fexceptions -g 
-grecord-gcc-switches -pipe -Wall -Werror=format-security 
-Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS 
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong 
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic 
-fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -g -Wall 
-Werror -Wextra -Wno-unused-parameter -I. 
-I/home/wcohen/rpmbuild/BUILD/libpfm-4.12.0/include -DCONFIG_PFMLIB_DEBUG 
-DCONFIG_PFMLIB_OS_LINUX -O2 -flto=auto -ffat-lto-objects -fexceptions -g 
-grecord-gcc-switches -pipe -Wall -Werror=format-security 
-Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS 
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong 
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic 
-fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -g -Wall 
-Werror -Wextra -Wno-unused-parameter -I. 
-I/home/wcohen/rpmbuild/BUILD/libpfm-4.12.0/lib/../include 
-DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -D_REENTRANT -I. 
-fvisibility=hidden -DCONFIG_PFMLIB_ARCH_X86 -DCONFIG_PFMLIB_ARCH_X86_64 -I. -c 
pfmlib_perf_event_pmu.c
pfmlib_perf_event_pmu.c: In function 'perf_table_alloc_event':
pfmlib_perf_event_pmu.c:293:47: error: pointer may be used after 'realloc' 
[-Werror=use-after-free]
  293 |         perf_pe_free = new_pe + (perf_pe_free - perf_pe);
      |                                               ^
pfmlib_perf_event_pmu.c:289:18: note: call to 'realloc' here
  289 |         new_pe = realloc(perf_pe, perf_pe_count * sizeof(perf_event_t));
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function 'perf_table_alloc_umask',
    inlined from 'gen_tracepoint_table' at pfmlib_perf_event_pmu.c:457:10:
pfmlib_perf_event_pmu.c:329:47: error: pointer may be used after 'realloc' 
[-Werror=use-after-free]
  329 |         perf_um_free = new_um + (perf_um_free - perf_um);
      |                                               ^
pfmlib_perf_event_pmu.c:325:18: note: call to 'realloc' here
  325 |         new_um = realloc(perf_um, perf_um_count * sizeof(*new_um));
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [/home/wcohen/rpmbuild/BUILD/libpfm-4.12.0/lib/../rules.mk:30: 
pfmlib_perf_event_pmu.o] Error 1
make[1]: Leaving directory '/home/wcohen/rpmbuild/BUILD/libpfm-4.12.0/lib'
make: *** [Makefile:49: all] Error 2
error: Bad exit status from /var/tmp/rpm-tmp.OFeziw (%build)

The logic is a bit convoluted in the perf_table_alloc_event and 
perf_table_alloc_umask. Why not compute perf_pe_end and perf_um_end directly 
from the values passed into the realloc?  Maybe something like the attached 
patch to address this.

-Will
diff -up libpfm-4.12.0/lib/pfmlib_perf_event_pmu.c.gcc12 libpfm-4.12.0/lib/pfmlib_perf_event_pmu.c
--- libpfm-4.12.0/lib/pfmlib_perf_event_pmu.c.gcc12	2021-12-16 16:29:42.000000000 -0500
+++ libpfm-4.12.0/lib/pfmlib_perf_event_pmu.c	2022-01-25 20:20:13.095174345 -0500
@@ -268,6 +268,7 @@ perf_table_alloc_event(void)
 {
 	perf_event_t *new_pe;
 	perf_event_t *p;
+	int perf_pe_used;
 
 	/*
 	 * if we need to allocate an event and we have not yet
@@ -285,13 +286,14 @@ retry:
 		return perf_pe_free++;
 
 	perf_pe_count += PERF_ALLOC_EVENT_COUNT;
+	perf_pe_used = perf_pe_free - perf_pe;
 	
 	new_pe = realloc(perf_pe, perf_pe_count * sizeof(perf_event_t));
 	if (!new_pe) 
 		return NULL;
 	
-	perf_pe_free = new_pe + (perf_pe_free - perf_pe);
-	perf_pe_end = perf_pe_free + PERF_ALLOC_EVENT_COUNT;
+	perf_pe_free = new_pe + perf_pe_used;
+	perf_pe_end = new_pe + perf_pe_count;
 	perf_pe = new_pe;
 
 	goto retry;
@@ -315,19 +317,21 @@ static perf_umask_t *
 perf_table_alloc_umask(void)
 {
 	perf_umask_t *new_um;
+	int perf_um_used;
 
 retry:
 	if (perf_um_free < perf_um_end)
 		return perf_um_free++;
 
 	perf_um_count += PERF_ALLOC_UMASK_COUNT;
+	perf_um_used = perf_um_free - perf_um;
 	
 	new_um = realloc(perf_um, perf_um_count * sizeof(*new_um));
 	if (!new_um) 
 		return NULL;
 	
-	perf_um_free = new_um + (perf_um_free - perf_um);
-	perf_um_end = perf_um_free + PERF_ALLOC_UMASK_COUNT;
+	perf_um_free = new_um + perf_um_used;
+	perf_um_end = new_um + perf_um_count;
 	perf_um = new_um;
 
 	goto retry;
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to