From ae413f79b24de558ac9ab925babd1fb86e0d21c7 Mon Sep 17 00:00:00 2001 From: Paul Floyd Date: Sun, 10 Sep 2023 15:05:57 +0200 Subject: [PATCH] Bug 474332 - aligned_alloc under Valgrind returns nullptr when alignment is not a multiple of sizeof(void *) At configure time use glibc version to set a HAVE flag for C17 aligned_alloc. The use the HAVE flag to select which redir macro to use. Also make the (normally unused) glibc ALIGNED_ALLOC macro the same as MEMALIGN, just in case. --- NEWS | 1 + configure.ac | 20 ++++++++++++++++++++ coregrind/m_replacemalloc/vg_replace_malloc.c | 23 ++++++++++++++++------- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index c3ee77d51..da6f4f816 100644 --- a/NEWS +++ b/NEWS @@ -74,6 +74,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 473745 must-be-redirected function - strlen 473870 FreeBSD 14 applications fail early at startup 473944 Handle mold linker split RW PT_LOAD segments correctly +474332 aligned_alloc under Valgrind returns nullptr when alignment is not a multiple of sizeof(void *) n-i-bz Allow arguments with spaces in .valgrindrc files To see details of a given bug, visit diff --git a/configure.ac b/configure.ac index e6c3f7995..d745497e8 100755 --- a/configure.ac +++ b/configure.ac @@ -5424,6 +5424,26 @@ CXXFLAGS=$safe_CXXFLAGS AM_CONDITIONAL([HAVE_SHARED_POINTER_ANNOTATION], [test x$ac_have_shared_pointer_annotation = xyes]) +# checking for GNU libc C17 aligned_alloc +# just check glibc version rather than trying to muck around +# checking the runtime behaviour or seeing if it is a weak alias +AC_MSG_CHECKING([for AT_GNU_LIBC_C17_ALIGNED_ALLOC]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +]], [[ +#if !defined(__GLIBC__) || __GLIBC__ != 2 || !defined(__GLIBC_MINOR__) || __GLIBC_MINOR__ < 38 +#error "not GNU libc 2.38 or later" +#endif +]])], [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_GNU_LIBC_C17_ALIGNED_ALLOC], 1, + [Define to 1 if you have GNU libc C17 aligned_alloc.]) + +], [ + AC_MSG_RESULT([no]) +]) + + #---------------------------------------------------------------------------- # Ok. We're done checking. diff --git a/coregrind/m_replacemalloc/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c index 6c6f0d60f..23bd26575 100644 --- a/coregrind/m_replacemalloc/vg_replace_malloc.c +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c @@ -2157,7 +2157,15 @@ extern int * __error(void) __attribute__((weak)); #define VG_ALIGNED_ALLOC_NO_SIZE_ZERO 1 #endif -#if defined (VGO_linux) && !defined(MUSL_LIBC) +#if defined (VGO_linux) && !defined(MUSL_LIBC) && !defined(HAVE_GNU_LIBC_C17_ALIGNED_ALLOC) + +/* + * Normally for GNU libc <= 2.37 aligned_alloc is a weak alias for memalign + * so this redir is not used. + * For libc 2.38 and later it is a separate function but then HAVE_GNU_LIBC_C17_ALIGNED_ALLOC + * should be true and this version doesn't get compiled. + * Leaving it here to be on the safe side. + */ #define ALIGNED_ALLOC(soname, fnname) \ \ @@ -2175,12 +2183,13 @@ extern int * __error(void) __attribute__((weak)); VERIFY_ALIGNMENT(&aligned_alloc_info); \ MALLOC_TRACE("aligned_alloc(al %llu, size %llu)", \ (ULong)alignment, (ULong)size ); \ - /* Test whether the alignment argument is valid. It must be \ - a power of two multiple of sizeof (void *). */ \ - if (alignment == 0 \ - || alignment % sizeof (void *) != 0 \ - || (alignment & (alignment - 1)) != 0) \ - return 0; \ + \ + /* Round up to minimum alignment if necessary. */ \ + if (alignment < VG_MIN_MALLOC_SZB) \ + alignment = VG_MIN_MALLOC_SZB; \ + \ + /* Round up to nearest power-of-two if necessary (like glibc). */ \ + while (0 != (alignment & (alignment - 1))) alignment++; \ \ mem = (void*)VALGRIND_NON_SIMD_CALL3( info.tl_memalign, \ alignment, orig_alignment, size ); \ -- 2.11.4.GIT