From: Paul Floyd Date: Sun, 5 Mar 2023 14:25:51 +0000 (+0100) Subject: Make aligned_alloc behave more like the underlying platform aligned_alloc X-Git-Tag: VALGRIND_3_21_0~149 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd20bb9c67f180e9e22b9b1694b3530c772ff73d;p=thirdparty%2Fvalgrind.git Make aligned_alloc behave more like the underlying platform aligned_alloc This is the third part of Bug 466104 aligned_alloc problems, part 1 Shouldn't affect Linux glibc. --- diff --git a/.gitignore b/.gitignore index 7cd35cc9e3..67e6b545fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1082,6 +1082,7 @@ /memcheck/tests/darwin/Makefile /memcheck/tests/darwin/Makefile.in /memcheck/tests/darwin/aio +/memcheck/tests/darwin/aligned_alloc /memcheck/tests/darwin/deep_badparam /memcheck/tests/darwin/env /memcheck/tests/darwin/ioctl-tiocsbrk @@ -1099,6 +1100,7 @@ /memcheck/tests/linux/*.stdout.diff /memcheck/tests/linux/*.stdout.out /memcheck/tests/linux/.deps +/memcheck/tests/linux/aligned_alloc /memcheck/tests/linux/brk /memcheck/tests/linux/capget /memcheck/tests/linux/check_preadv2_pwritev2 @@ -1193,6 +1195,7 @@ /memcheck/tests/solaris/.deps /memcheck/tests/solaris/Makefile /memcheck/tests/solaris/Makefile.in +/memcheck/tests/solaris/aligned_alloc /memcheck/tests/solaris/brk /memcheck/tests/solaris/context_stack_die /memcheck/tests/solaris/door_data diff --git a/coregrind/m_replacemalloc/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c index 494ef96371..1bdcac7d3e 100644 --- a/coregrind/m_replacemalloc/vg_replace_malloc.c +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c @@ -1892,14 +1892,14 @@ extern int *___errno (void) __attribute__((weak)); * alignment supported by the implementation the function shall * fail by returning a null pointer". * - * Linux glibc, the man page claims that the alignment must be + * Linux glibc. The man page claims that the alignment must be * a power of two and that size should be a multiple of alignment. * However the only case that returns EINVAL (glibc 2.34) * is if the alignement is > SIZE_MAX / 2 + 1 * Also this is just a weak alias for memalign so this wrapper - * has no effect on Linux. + * has no effect on Linux glibc. * - * Linux musl, the alignment must be a power of 2 else + * Linux musl. The alignment must be a power of 2 else * returns einval. The value of the alignment is clamped * to a minumum of UNIT (16). * @@ -1908,16 +1908,25 @@ extern int *___errno (void) __attribute__((weak)); * The code checks that the alignment is a power of * 2 and not less than the minumum alignment (1) * - * Solaris: doesn't seem to exist on 11.3 - * Illumos: invalid if the size is 0, the alignment is 0, the + * Solaris. Doesn't seem to exist on 11.3 + * Illumos. Invalid if the size is 0, the alignment is 0, the * alignment is not a multiple of 4 (no power of 2 * requirement even though the manpage claims is) or the * alignment is greater than MAX_ALIGN (whatever that is). * Wrapper function that just calls memalign * + * Darwin. Does enforce size bing an integer multiple of + * alignment. + * */ -#if defined (VGO_linux) +#if defined(VGO_darwin) +#define VG_ALIGNED_ALLOC_SIZE_MULTIPLE_ALIGN 1 +#else +#define VG_ALIGNED_ALLOC_SIZE_MULTIPLE_ALIGN 0 +#endif + +#if defined (VGO_linux) && !defined(MUSL_LIBC) #define ALIGNED_ALLOC(soname, fnname) \ \ @@ -1928,7 +1937,6 @@ extern int *___errno (void) __attribute__((weak)); { \ void *mem; \ \ - TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(alignment); \ TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(size); \ MALLOC_TRACE("aligned_alloc(al %llu, size %llu)", \ (ULong)alignment, (ULong)size ); \ @@ -1959,12 +1967,16 @@ extern int *___errno (void) __attribute__((weak)); MALLOC_TRACE("aligned_alloc(al %llu, size %llu)", \ (ULong)alignment, (ULong)size ); \ if (alignment == 0 \ - || size % alignment != 0 \ + || (VG_ALIGNED_ALLOC_SIZE_MULTIPLE_ALIGN && (size % alignment != 0)) \ || (alignment & (alignment - 1)) != 0) { \ SET_ERRNO_EINVAL; \ return 0; \ } \ \ + /* Round up to minimum alignment if necessary. */ \ + if (alignment < VG_MIN_MALLOC_SZB) \ + alignment = VG_MIN_MALLOC_SZB; \ + \ mem = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, \ alignment, size ); \ \ diff --git a/memcheck/tests/darwin/Makefile.am b/memcheck/tests/darwin/Makefile.am index 4e34a22ec2..c180964dd6 100644 --- a/memcheck/tests/darwin/Makefile.am +++ b/memcheck/tests/darwin/Makefile.am @@ -7,6 +7,7 @@ noinst_HEADERS = scalar.h EXTRA_DIST = \ aio.stderr.exp aio.vgtest \ + aligned_alloc.stderr.exp aligned_alloc.vgtest \ deep_badparam.stderr.exp deep_badparam.stdout.exp deep_badparam.vgtest \ env.stderr.exp env.vgtest \ ioctl-tiocsbrk.stderr.exp ioctl-tiocsbrk.vgtest \ @@ -20,6 +21,7 @@ EXTRA_DIST = \ check_PROGRAMS = \ aio \ + aligned_alloc \ deep_badparam \ env \ ioctl-tiocsbrk \ diff --git a/memcheck/tests/darwin/aligned_alloc.c b/memcheck/tests/darwin/aligned_alloc.c new file mode 100644 index 0000000000..13b04525a5 --- /dev/null +++ b/memcheck/tests/darwin/aligned_alloc.c @@ -0,0 +1,40 @@ +#include +#include +#include + +int main(void) +{ + char* p = NULL; + int res; + + // zero size + p = aligned_alloc(0, 8); + assert(p == NULL && errno == EINVAL); + errno = 0; + // non multiple of alignment fails on Darwin + p = aligned_alloc(8, 25); + assert(p == NULL && errno == EINVAL); + errno = 0; + // align not power of 2 + p = aligned_alloc(40, 160); + assert(p == NULL && errno == EINVAL); + errno = 0; + // the test below causes a segfault with musl 1.2.2 + // apparently it has been + + // too big + if (sizeof(size_t) == 8) + { + p = aligned_alloc(16, 1UL<<48); + } + else + { + p = NULL; + errno = ENOMEM; + } + + assert(p == NULL && errno == ENOMEM); + +} + + diff --git a/memcheck/tests/darwin/aligned_alloc.stderr.exp b/memcheck/tests/darwin/aligned_alloc.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/darwin/aligned_alloc.vgtest b/memcheck/tests/darwin/aligned_alloc.vgtest new file mode 100644 index 0000000000..a20bccb007 --- /dev/null +++ b/memcheck/tests/darwin/aligned_alloc.vgtest @@ -0,0 +1,2 @@ +prog: aligned_alloc +vgopts: -q diff --git a/memcheck/tests/freebsd/errno_aligned_allocs.c b/memcheck/tests/freebsd/errno_aligned_allocs.c index b8954be773..7faffd5307 100644 --- a/memcheck/tests/freebsd/errno_aligned_allocs.c +++ b/memcheck/tests/freebsd/errno_aligned_allocs.c @@ -61,8 +61,9 @@ int main(void) assert(p == NULL && errno == EINVAL); errno = 0; // non multiple of alignment passes on FreeBSD - //p = aligned_alloc(8, 25); - //assert(p == NULL && errno == EINVAL); + p = aligned_alloc(8, 25); + assert(p && ((size_t)p % 8U == 0U)); + free(p); //errno = 0; // align not power of 2 p = aligned_alloc(40, 160); diff --git a/memcheck/tests/freebsd/errno_aligned_allocs.stderr.exp b/memcheck/tests/freebsd/errno_aligned_allocs.stderr.exp index eb42921c60..df22e9a5bb 100644 --- a/memcheck/tests/freebsd/errno_aligned_allocs.stderr.exp +++ b/memcheck/tests/freebsd/errno_aligned_allocs.stderr.exp @@ -2,7 +2,7 @@ HEAP SUMMARY: in use at exit: 0 bytes in 0 blocks - total heap usage: 0 allocs, 0 frees, 0 bytes allocated + total heap usage: 1 allocs, 1 frees, 25 bytes allocated For a detailed leak analysis, rerun with: --leak-check=full diff --git a/memcheck/tests/linux/Makefile.am b/memcheck/tests/linux/Makefile.am index af26730c37..895f76ed69 100644 --- a/memcheck/tests/linux/Makefile.am +++ b/memcheck/tests/linux/Makefile.am @@ -4,6 +4,7 @@ include $(top_srcdir)/Makefile.tool-tests.am dist_noinst_SCRIPTS = filter_stderr EXTRA_DIST = \ + aligned_alloc.c aligned_alloc.vgtest aligned_alloc.stderr.exp \ brk.stderr.exp brk.vgtest \ capget.vgtest capget.stderr.exp capget.stderr.exp2 capget.stderr.exp3 \ debuginfod-check.stderr.exp debuginfod-check.vgtest.in \ diff --git a/memcheck/tests/linux/aligned_alloc.c b/memcheck/tests/linux/aligned_alloc.c new file mode 100644 index 0000000000..15955ff845 --- /dev/null +++ b/memcheck/tests/linux/aligned_alloc.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include "../../../config.h" + +int main(void) +{ +#if defined(MUSL_LIBC) + char* p = NULL; + int res; + + // zero size + p = aligned_alloc(0, 8); + assert(p == NULL && errno == EINVAL); + errno = 0; + // non multiple of alignment passes on FreeBSD + p = aligned_alloc(8, 25); + assert(p && ((size_t)p % 8U == 0U)); + free(p); + //errno = 0; + // align not power of 2 + p = aligned_alloc(40, 160); + assert(p == NULL && errno == EINVAL); + errno = 0; + // the test below causes a segfault with musl 1.2.2 + // apparently it has been fixed in 1.2.3 +#if 0 + // too big + if (sizeof(size_t) == 8) + { + p = aligned_alloc(16, 1UL<<48); + } + else + { + p = NULL; + errno = ENOMEM; + } +#endif + assert(p == NULL && errno == ENOMEM); +#endif +} + + diff --git a/memcheck/tests/linux/aligned_alloc.stderr.exp b/memcheck/tests/linux/aligned_alloc.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/linux/aligned_alloc.vgtest b/memcheck/tests/linux/aligned_alloc.vgtest new file mode 100644 index 0000000000..07c1c4faf7 --- /dev/null +++ b/memcheck/tests/linux/aligned_alloc.vgtest @@ -0,0 +1 @@ +prog: aligned_alloc diff --git a/memcheck/tests/solaris/Makefile.am b/memcheck/tests/solaris/Makefile.am index 024856901c..fe1e2ca3fb 100644 --- a/memcheck/tests/solaris/Makefile.am +++ b/memcheck/tests/solaris/Makefile.am @@ -12,6 +12,7 @@ dist_noinst_SCRIPTS = \ noinst_HEADERS = scalar.h EXTRA_DIST = \ + aligned_alloc.stderr.exp aligned_alloc.vgtest \ brk.stderr.exp brk.stdout.exp brk.vgtest \ context_stack_die.stderr.exp context_stack_die.stdout.exp context_stack_die.vgtest \ door_data.stderr.exp door_data.stdout.exp door_data.vgtest \ @@ -58,6 +59,7 @@ EXTRA_DIST = \ memalign.vgtest memalign.stderr.exp check_PROGRAMS = \ + aligned_alloc \ brk \ context_stack_die \ door_data \ diff --git a/memcheck/tests/solaris/aligned_alloc.c b/memcheck/tests/solaris/aligned_alloc.c new file mode 100644 index 0000000000..36456623e9 --- /dev/null +++ b/memcheck/tests/solaris/aligned_alloc.c @@ -0,0 +1,41 @@ +#include +#include +#include + +int main(void) +{ + char* p = NULL; + int res; + + // zero size + p = aligned_alloc(0, 8); + assert(p == NULL && errno == EINVAL); + errno = 0; + // non multiple of alignment passes on Solaris + p = aligned_alloc(8, 25); + assert(p && ((size_t)p % 8U == 0U)); + free(p); + //errno = 0; + // align not power of 2 + p = aligned_alloc(40, 160); + assert(p == NULL && errno == EINVAL); + errno = 0; + // the test below causes a segfault with musl 1.2.2 + // apparently it has been + + // too big + if (sizeof(size_t) == 8) + { + p = aligned_alloc(16, 1UL<<48); + } + else + { + p = NULL; + errno = ENOMEM; + } + + assert(p == NULL && errno == ENOMEM); + +} + + diff --git a/memcheck/tests/solaris/aligned_alloc.stderr.exp b/memcheck/tests/solaris/aligned_alloc.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/solaris/aligned_alloc.vgtest b/memcheck/tests/solaris/aligned_alloc.vgtest new file mode 100644 index 0000000000..07c1c4faf7 --- /dev/null +++ b/memcheck/tests/solaris/aligned_alloc.vgtest @@ -0,0 +1 @@ +prog: aligned_alloc