]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Make aligned_alloc behave more like the underlying platform aligned_alloc
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sun, 5 Mar 2023 14:25:51 +0000 (15:25 +0100)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sun, 5 Mar 2023 14:25:51 +0000 (15:25 +0100)
This is the third part of
Bug 466104 aligned_alloc problems, part 1

Shouldn't affect Linux glibc.

16 files changed:
.gitignore
coregrind/m_replacemalloc/vg_replace_malloc.c
memcheck/tests/darwin/Makefile.am
memcheck/tests/darwin/aligned_alloc.c [new file with mode: 0644]
memcheck/tests/darwin/aligned_alloc.stderr.exp [new file with mode: 0644]
memcheck/tests/darwin/aligned_alloc.vgtest [new file with mode: 0644]
memcheck/tests/freebsd/errno_aligned_allocs.c
memcheck/tests/freebsd/errno_aligned_allocs.stderr.exp
memcheck/tests/linux/Makefile.am
memcheck/tests/linux/aligned_alloc.c [new file with mode: 0644]
memcheck/tests/linux/aligned_alloc.stderr.exp [new file with mode: 0644]
memcheck/tests/linux/aligned_alloc.vgtest [new file with mode: 0644]
memcheck/tests/solaris/Makefile.am
memcheck/tests/solaris/aligned_alloc.c [new file with mode: 0644]
memcheck/tests/solaris/aligned_alloc.stderr.exp [new file with mode: 0644]
memcheck/tests/solaris/aligned_alloc.vgtest [new file with mode: 0644]

index 7cd35cc9e3da521fdb44000880aa65641e1f198d..67e6b545fe32eadfb8d47723eb42d66c293554c7 100644 (file)
 /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
 /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
 /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
index 494ef96371f0981077d513a9d3b829770c2750b4..1bdcac7d3e6f2a860021181feec8925e7e478c17 100644 (file)
@@ -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 ); \
        \
index 4e34a22ec2f7fbf408e6e091bf8987685f81c42b..c180964dd6011c4ddfd9fa63402fd8d00a68ad93 100644 (file)
@@ -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 (file)
index 0000000..13b0452
--- /dev/null
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+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 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/darwin/aligned_alloc.vgtest b/memcheck/tests/darwin/aligned_alloc.vgtest
new file mode 100644 (file)
index 0000000..a20bccb
--- /dev/null
@@ -0,0 +1,2 @@
+prog: aligned_alloc
+vgopts: -q
index b8954be7738048f3586b7063cbf38b8a39166209..7faffd5307a88030193035fda29ec77f2c21b0d9 100644 (file)
@@ -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);
index eb42921c60d30d353b87028433fb4268e0d24a06..df22e9a5bba246c572c7e19898cac7fc65712bfb 100644 (file)
@@ -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
 
index af26730c371e4c8cae1ef54c4b35444fd8375b6f..895f76ed69041f8ea5d98356d9098bd3c060dcaa 100644 (file)
@@ -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 (file)
index 0000000..15955ff
--- /dev/null
@@ -0,0 +1,43 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#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 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/linux/aligned_alloc.vgtest b/memcheck/tests/linux/aligned_alloc.vgtest
new file mode 100644 (file)
index 0000000..07c1c4f
--- /dev/null
@@ -0,0 +1 @@
+prog: aligned_alloc
index 024856901c0b723e636b83480a2ad54a6538641e..fe1e2ca3fb34b06651bc31c754b41d2bd26e54e0 100644 (file)
@@ -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 (file)
index 0000000..3645662
--- /dev/null
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+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 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/solaris/aligned_alloc.vgtest b/memcheck/tests/solaris/aligned_alloc.vgtest
new file mode 100644 (file)
index 0000000..07c1c4f
--- /dev/null
@@ -0,0 +1 @@
+prog: aligned_alloc