diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp --- a/libcxx/src/new.cpp +++ b/libcxx/src/new.cpp @@ -73,32 +73,22 @@ if (nh) nh(); else -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif + std::__throw_bad_alloc(); } return p; } _LIBCPP_WEAK -void* -operator new(size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new(size_t size, const std::nothrow_t&) noexcept { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new(size); + try { +#endif + return ::operator new(size); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + return nullptr; } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; +#endif } _LIBCPP_WEAK @@ -109,22 +99,16 @@ } _LIBCPP_WEAK -void* -operator new[](size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new[](size_t size, const std::nothrow_t&) noexcept { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new[](size); + try { +#endif + return ::operator new[](size); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + return nulltpr; } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; +#endif } _LIBCPP_WEAK @@ -192,34 +176,23 @@ std::new_handler nh = std::get_new_handler(); if (nh) nh(); - else { -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif - } + else + std::__throw_bad_alloc(); } return p; } _LIBCPP_WEAK -void* -operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new(size, alignment); + try { +#endif + return ::operator new(size, alignment); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + return nullptr; } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; +#endif } _LIBCPP_WEAK @@ -230,22 +203,16 @@ } _LIBCPP_WEAK -void* -operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new[](size, alignment); + try { +#endif + return ::operator new[](size, alignment); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + return nullptr; } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; +#endif } _LIBCPP_WEAK diff --git a/libcxx/test/libcxx/language.support/support.dynamic/new_dont_return_nullptr.pass.cpp b/libcxx/test/libcxx/language.support/support.dynamic/new_dont_return_nullptr.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/language.support/support.dynamic/new_dont_return_nullptr.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// void* operator new(std::size_t); +// void* operator new(std::size_t, std::align_val_t); +// void* operator new[](std::size_t); +// void* operator new[](std::size_t, std::align_val_t); + +// This test ensures that we abort the program instead of returning nullptr +// when we fail to satisfy the allocation request. The throwing versions of +// `operator new` must never return nullptr on failure to allocate (per the +// Standard) and the compiler actually relies on that for optimizations. +// Returning nullptr from the throwing `operator new` can basically result +// in miscompiles. + +// REQUIRES: has-unix-headers +// REQUIRES: no-exceptions +// UNSUPPORTED: c++03, c++11, c++14 + +#include +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + EXPECT_DEATH((void)operator new(std::numeric_limits::max())); + EXPECT_DEATH((void)operator new(std::numeric_limits::max(), static_cast(32))); + EXPECT_DEATH((void)operator new[](std::numeric_limits::max())); + EXPECT_DEATH((void)operator new[](std::numeric_limits::max(), static_cast(32))); + return 0; +} diff --git a/libcxxabi/src/stdlib_new_delete.cpp b/libcxxabi/src/stdlib_new_delete.cpp --- a/libcxxabi/src/stdlib_new_delete.cpp +++ b/libcxxabi/src/stdlib_new_delete.cpp @@ -17,6 +17,15 @@ #error The _THROW_BAD_ALLOC and _LIBCXXABI_WEAK libc++ macros must \ already be defined by libc++. #endif + +static void __throw_bad_alloc() { +#ifndef _LIBCXXABI_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + std::abort(); +#endif +} + // Implement all new and delete operators as weak definitions // in this shared library, so that they can be overridden by programs // that define non-weak copies of the functions. @@ -36,32 +45,22 @@ if (nh) nh(); else -#ifndef _LIBCXXABI_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif + __throw_bad_alloc(); } return p; } _LIBCXXABI_WEAK -void* -operator new(size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new(size_t size, const std::nothrow_t&) noexcept { #ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new(size); + try { +#endif + return ::operator new(size); #ifndef _LIBCXXABI_NO_EXCEPTIONS + } catch (...) { + return nullptr; } - catch (...) - { - } -#endif // _LIBCXXABI_NO_EXCEPTIONS - return p; +#endif } _LIBCXXABI_WEAK @@ -72,22 +71,16 @@ } _LIBCXXABI_WEAK -void* -operator new[](size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new[](size_t size, const std::nothrow_t&) noexcept { #ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new[](size); + try { +#endif + return ::operator new[](size); #ifndef _LIBCXXABI_NO_EXCEPTIONS + } catch (...) { + return nullptr; } - catch (...) - { - } -#endif // _LIBCXXABI_NO_EXCEPTIONS - return p; +#endif } _LIBCXXABI_WEAK @@ -155,34 +148,23 @@ std::new_handler nh = std::get_new_handler(); if (nh) nh(); - else { -#ifndef _LIBCXXABI_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif - } + else + __throw_bad_alloc(); } return p; } _LIBCXXABI_WEAK -void* -operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { #ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new(size, alignment); + try { +#endif + return ::operator new(size, alignment); #ifndef _LIBCXXABI_NO_EXCEPTIONS + } catch (...) { + return nullptr; } - catch (...) - { - } -#endif // _LIBCXXABI_NO_EXCEPTIONS - return p; +#endif } _LIBCXXABI_WEAK @@ -193,22 +175,16 @@ } _LIBCXXABI_WEAK -void* -operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; +void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { #ifndef _LIBCXXABI_NO_EXCEPTIONS - try - { -#endif // _LIBCXXABI_NO_EXCEPTIONS - p = ::operator new[](size, alignment); + try { +#endif + return ::operator new[](size, alignment); #ifndef _LIBCXXABI_NO_EXCEPTIONS + } catch (...) { + return nullptr; } - catch (...) - { - } -#endif // _LIBCXXABI_NO_EXCEPTIONS - return p; +#endif } _LIBCXXABI_WEAK