From: Paul Floyd Date: Wed, 8 Mar 2023 22:10:22 +0000 (+0100) Subject: Make operator new aligned more like the standalone versions X-Git-Tag: VALGRIND_3_21_0~129 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4affb0ab725a59da786fee4b918b338eec615fe;p=thirdparty%2Fvalgrind.git 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. --- diff --git a/.gitignore b/.gitignore index a4c7b510ba..d5e341063e 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/coregrind/m_replacemalloc/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c index 2b0879cd86..05bc9a4f61 100644 --- a/coregrind/m_replacemalloc/vg_replace_malloc.c +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c @@ -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) { \ diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 98cecb9ca2..c9008ec5e7 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -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 index 0000000000..647fa5a850 --- /dev/null +++ b/memcheck/tests/sized_aligned_new_delete_misaligned.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "valgrind.h" + +int main() { + std::align_val_t misalign(static_cast(63U)); + std::align_val_t zeroalign(static_cast(0U)); + std::align_val_t onealign(static_cast(1U)); + std::align_val_t align(static_cast(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 index 0000000000..afbd817bad --- /dev/null +++ b/memcheck/tests/sized_aligned_new_delete_misaligned.stderr.exp @@ -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 index 0000000000..fc7b6f4712 --- /dev/null +++ b/memcheck/tests/sized_aligned_new_delete_misaligned.vgtest @@ -0,0 +1,3 @@ +prog: sized_aligned_new_delete_misaligned +prereq: test -e ./sized_aligned_new_delete_misaligned +vgopts: -q