]> sourceware.org Git - valgrind.git/commitdiff
Make operator new aligned more like the standalone versions
authorPaul Floyd <pjfloyd@wanadoo.fr>
Wed, 8 Mar 2023 22:10:22 +0000 (23:10 +0100)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Wed, 8 Mar 2023 22:10:22 +0000 (23:10 +0100)
If the alignment is not a power of two return nullptr for the
nothrow overload and bomb for the throwing overload.

.gitignore
coregrind/m_replacemalloc/vg_replace_malloc.c
memcheck/tests/Makefile.am
memcheck/tests/sized_aligned_new_delete_misaligned.cpp [new file with mode: 0644]
memcheck/tests/sized_aligned_new_delete_misaligned.stderr.exp [new file with mode: 0644]
memcheck/tests/sized_aligned_new_delete_misaligned.vgtest [new file with mode: 0644]

index a4c7b510bab152b629e4d195c9d98bdc1fa06e33..d5e341063eab9dc99e8e70a1e037579179de2ce9 100644 (file)
 /memcheck/tests/sh-mem
 /memcheck/tests/sh-mem-random
 /memcheck/tests/sized_aligned_new_delete_args
+/memcheck/tests/sized_aligned_new_delete_misaligned
 /memcheck/tests/sigaltstack
 /memcheck/tests/sigkill
 /memcheck/tests/signal2
index 2b0879cd86dae3761ea5e7287e91d54b42a0a0c7..05bc9a4f613130a4bdd2af323688938b7f3078da 100644 (file)
@@ -294,13 +294,15 @@ extern int *___errno (void) __attribute__((weak));
       TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(n); \
       MALLOC_TRACE(#fnname "(size %llu, al %llu)", (ULong)n, (ULong)alignment ); \
       \
+      if ((alignment == 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++; \
-      \
       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_##vg_replacement, n, alignment ); \
       MALLOC_TRACE(" = %p\n", v ); \
       if (!v) SET_ERRNO_ENOMEM; \
@@ -367,13 +369,19 @@ extern int *___errno (void) __attribute__((weak));
       TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(n);           \
       MALLOC_TRACE(#fnname "(size %llu, al %llu)", (ULong)n, (ULong)alignment ); \
       \
+      if ((alignment == 0) \
+       || ((alignment & (alignment - 1)) != 0)) { \
+         VALGRIND_PRINTF( \
+            "new/new[] aligned failed and should throw an exception, but Valgrind\n"); \
+         VALGRIND_PRINTF_BACKTRACE( \
+            "   cannot throw exceptions and so is aborting instead.  Sorry.\n"); \
+         my_exit(1); \
+      } \
+      \
       /* 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++; \
-      \
       v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_##vg_replacement, n, alignment ); \
       MALLOC_TRACE(" = %p\n", v ); \
       if (NULL == v) { \
index 98cecb9ca2c6c1b59018e18a7910cab30fb2c058..c9008ec5e754e4b4027b13ee5a8ad64323123cc9 100644 (file)
@@ -142,6 +142,8 @@ EXTRA_DIST = \
        sized_aligned_new_delete_args.stderr.exp \
                sized_aligned_new_delete_args.vgtest \
                sized_aligned_new_delete_args.stderr.exp_32 \
+       sized_aligned_new_delete_misaligned.stderr.exp \
+               sized_aligned_new_delete_misaligned.vgtest \
        deep-backtrace.vgtest deep-backtrace.stderr.exp \
        demangle.stderr.exp demangle.vgtest \
        big_debuginfo_symbol.stderr.exp big_debuginfo_symbol.vgtest \
@@ -489,7 +491,8 @@ cdebug_zlib_gnu_CFLAGS = $(AM_CFLAGS) -g -gz=zlib-gnu @FLAG_W_NO_UNINITIALIZED@
 endif
 
 if HAVE_ALIGNED_CXX_ALLOC
-check_PROGRAMS += cxx17_aligned_new sized_aligned_new_delete_args
+check_PROGRAMS += cxx17_aligned_new sized_aligned_new_delete_args \
+       sized_aligned_new_delete_misaligned
 endif
 
 if HAVE_PTHREAD_BARRIER
@@ -552,6 +555,8 @@ cxx17_aligned_new_SOURCES  = cxx17_aligned_new.cpp
 cxx17_aligned_new_CXXFLAGS = -std=c++17 @FLAG_W_NO_MISMATCHED_NEW_DELETE@
 sized_aligned_new_delete_args_SOURCES = sized_aligned_new_delete_args.cpp
 sized_aligned_new_delete_args_CXXFLAGS = ${AM_CXXFLAGS} -std=c++17
+sized_aligned_new_delete_misaligned_SOURCES = sized_aligned_new_delete_misaligned.cpp
+sized_aligned_new_delete_misaligned_CXXFLAGS = ${AM_CXXFLAGS} -std=c++17
 endif
 
 demangle_SOURCES = demangle.cpp
diff --git a/memcheck/tests/sized_aligned_new_delete_misaligned.cpp b/memcheck/tests/sized_aligned_new_delete_misaligned.cpp
new file mode 100644 (file)
index 0000000..647fa5a
--- /dev/null
@@ -0,0 +1,86 @@
+#include <cstdlib>
+#include <new>
+#include <iostream>
+#include <cassert>
+#include <cstdio>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "valgrind.h"
+
+int main() {
+    std::align_val_t misalign(static_cast<std::align_val_t>(63U));
+    std::align_val_t zeroalign(static_cast<std::align_val_t>(0U));
+    std::align_val_t onealign(static_cast<std::align_val_t>(1U));
+    std::align_val_t align(static_cast<std::align_val_t>(64U));
+    size_t size(32);
+    std::nothrow_t tag;
+    void *mem = nullptr;
+    
+    // libc++ will allocate something for size zero
+    // but libstdc++ doesn't
+    mem = operator new(size, zeroalign, tag);
+    if (RUNNING_ON_VALGRIND) {
+       assert(!mem);
+    }
+    operator delete(mem, zeroalign, tag);
+    mem = nullptr;
+    
+    mem = operator new(size, onealign, tag);
+    assert(mem);
+    operator delete(mem, onealign, tag);
+    mem = nullptr;
+    
+    mem = operator new(size, align);
+    operator delete(mem, misalign);
+    mem = nullptr;
+    
+    mem = operator new[](size, align);
+    operator delete[](mem, misalign);
+    mem = nullptr;
+    
+    // doesn't matter that tag is uninit
+    // don't want to see an error
+    mem = operator new(size, misalign, tag);
+    operator delete(mem, misalign, tag);
+    assert(!mem);
+
+    mem = operator new[](size, misalign, tag);
+    operator delete[](mem, misalign, tag);
+    assert(!mem);
+    
+    mem = operator new(size, align);
+    operator delete(mem, size, misalign);
+    mem = nullptr;
+    
+    mem = operator new[](size, align);
+    operator delete[](mem, size, misalign);
+    
+    // the last two throw exceptions in C++
+    int pid;
+    int status;
+    pid = fork();
+    if (pid == -1) {
+       perror("fork");
+       exit(1);
+    }       
+    if (pid == 0) {
+        // child
+        mem = operator new(size, misalign);
+        // should throw
+        assert(false);
+    }
+    waitpid(pid, &status, 0);
+    pid = fork();
+    if (pid == -1) {
+       perror("fork");
+       exit(1);
+    }       
+    if (pid == 0) {
+        // child
+        mem = operator new[](size, misalign);
+        // should throw
+        assert(false);
+    }
+    waitpid(pid, &status, 0);
+}
diff --git a/memcheck/tests/sized_aligned_new_delete_misaligned.stderr.exp b/memcheck/tests/sized_aligned_new_delete_misaligned.stderr.exp
new file mode 100644 (file)
index 0000000..afbd817
--- /dev/null
@@ -0,0 +1,10 @@
+new/new[] aligned failed and should throw an exception, but Valgrind
+   cannot throw exceptions and so is aborting instead.  Sorry.
+   ...
+   by 0x........: operator new(unsigned long, std::align_val_t) (vg_replace_malloc.c:...)
+   by 0x........: main (sized_aligned_new_delete_misaligned.cpp:69)
+new/new[] aligned failed and should throw an exception, but Valgrind
+   cannot throw exceptions and so is aborting instead.  Sorry.
+   ...
+   by 0x........: operator new[](unsigned long, std::align_val_t) (vg_replace_malloc.c:...)
+   by 0x........: main (sized_aligned_new_delete_misaligned.cpp:81)
diff --git a/memcheck/tests/sized_aligned_new_delete_misaligned.vgtest b/memcheck/tests/sized_aligned_new_delete_misaligned.vgtest
new file mode 100644 (file)
index 0000000..fc7b6f4
--- /dev/null
@@ -0,0 +1,3 @@
+prog: sized_aligned_new_delete_misaligned
+prereq: test -e ./sized_aligned_new_delete_misaligned
+vgopts: -q
This page took 0.043097 seconds and 5 git commands to generate.