Make operator new aligned more like the standalone versions

If the alignment is not a power of two return nullptr for the
nothrow overload and bomb for the throwing overload.
This commit is contained in:
Paul Floyd 2023-03-08 23:10:22 +01:00
parent bb5e8df560
commit d4affb0ab7
6 changed files with 120 additions and 7 deletions

1
.gitignore vendored
View File

@ -962,6 +962,7 @@
/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

View 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) { \

View 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

View File

@ -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);
}

View File

@ -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)

View File

@ -0,0 +1,3 @@
prog: sized_aligned_new_delete_misaligned
prereq: test -e ./sized_aligned_new_delete_misaligned
vgopts: -q