Commit 39018ad5 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Fix crash in exception_wrapper::get_exception<>

Summary:
[Folly] Fix crash in `exception_wrapper::get_exception<>`.

When the contained object is unthrown and does not inherit `std::exception`, `get_exception` templated over a type that does not inherit `std::exception` must throw and catch internally and may then return a pointer to the internally thrown object, which has since been deallocated.

Attempting to dereference that pointer is undefined behavior is correctly caught by ASAN as heap-use-after-free.

Fix it by storing objects not inheriting `std::exception` using only the `std::exception_ptr` representation.

As a downside, we no longer get the small-object optimization or the non-throwing optimization for objects which do not inherit `std::exception`. But this is not likely to be terribly concerning in practice.

Reviewed By: ericniebler

Differential Revision: D6504911

fbshipit-source-id: 0065de911733b5cab87be55e7e4e47f0a9c09140
parent a335700f
main v2022.02.14.00 v2022.02.07.00 v2022.01.31.00 v2022.01.24.00 v2022.01.17.00 v2022.01.10.00 v2022.01.03.00 v2021.12.27.00 v2021.12.20.00 v2021.12.13.00 v2021.12.06.00 v2021.11.29.00 v2021.11.15.00 v2021.11.08.00 v2021.11.01.00 v2021.10.25.00 v2021.10.18.00 v2021.10.11.00 v2021.10.04.00 v2021.09.27.00 v2021.09.20.00 v2021.09.13.00 v2021.09.06.00 v2021.08.30.00 v2021.08.23.00 v2021.08.02.00 v2021.07.22.00 v2021.07.20.01 v2021.07.20.00 v2021.06.28.00 v2021.06.14.00 v2021.06.07.00 v2021.05.31.00 v2021.05.24.00 v2021.05.17.00 v2021.05.10.00 v2021.05.03.00 v2021.04.26.00 v2021.04.19.00 v2021.04.12.00 v2021.04.05.00 v2021.03.29.00 v2021.03.22.00 v2021.03.15.00 v2021.03.08.00 v2021.03.01.00 v2021.02.22.00 v2021.02.15.00 v2021.02.08.00 v2021.02.01.00 v2021.01.25.00 v2021.01.18.01 v2021.01.18.00 v2021.01.11.00 v2021.01.04.00 v2020.12.28.00 v2020.12.21.00 v2020.12.14.00 v2020.12.07.00 v2020.11.30.00 v2020.11.23.00 v2020.11.16.00 v2020.11.09.00 v2020.11.02.00 v2020.10.26.00 v2020.10.19.00 v2020.10.12.00 v2020.10.05.00 v2020.09.28.00 v2020.09.21.00 v2020.09.14.00 v2020.09.07.00 v2020.08.31.00 v2020.08.24.00 v2020.08.17.00 v2020.08.10.00 v2020.08.03.00 v2020.07.27.00 v2020.07.20.00 v2020.07.13.00 v2020.07.06.00 v2020.06.29.00 v2020.06.15.00 v2020.06.08.00 v2020.06.01.00 v2020.05.25.00 v2020.05.18.00 v2020.05.11.00 v2020.05.04.00 v2020.04.27.00 v2020.04.20.00 v2020.04.13.00 v2020.04.06.00 v2020.03.30.00 v2020.03.23.00 v2020.03.16.00 v2020.03.09.00 v2020.03.02.00 v2020.02.24.00 v2020.02.17.00 v2020.02.10.00 v2020.02.03.00 v2020.01.27.00 v2020.01.20.00 v2020.01.13.00 v2020.01.06.00 v2019.12.30.00 v2019.12.23.00 v2019.12.16.00 v2019.12.09.00 v2019.12.06.00 v2019.12.02.00 v2019.11.11.00 v2019.11.04.00 v2019.10.28.00 v2019.10.21.00 v2019.10.14.00 v2019.10.07.00 v2019.09.30.00 v2019.09.23.00 v2019.09.16.00 v2019.09.09.00 v2019.09.02.00 v2019.08.26.00 v2019.08.19.00 v2019.08.12.00 v2019.08.05.00 v2019.07.29.00 v2019.07.22.00 v2019.06.17.00 v2019.06.10.00 v2019.06.03.00 v2019.05.27.00 v2019.05.20.00 v2019.05.13.00 v2019.05.06.00 v2019.04.29.00 v2019.04.22.00 v2019.04.15.00 v2019.04.08.00 v2019.04.01.00 v2019.03.25.00 v2019.03.18.00 v2019.03.04.00 v2019.02.25.00 v2019.02.18.00 v2019.02.11.00 v2019.02.04.00 v2019.01.28.00 v2019.01.21.00 v2019.01.14.00 v2019.01.07.00 v2018.12.31.00 v2018.12.24.00 v2018.12.17.00 v2018.12.10.00 v2018.12.03.00 v2018.11.26.00 v2018.11.19.00 v2018.11.12.00 v2018.11.05.00 v2018.10.29.00 v2018.10.22.00 v2018.10.15.00 v2018.10.08.00 v2018.10.01.00 v2018.09.24.00 v2018.09.17.00 v2018.09.10.01 v2018.09.10.00 v2018.09.03.01 v2018.09.03.00 v2018.08.27.00 v2018.08.20.00 v2018.08.13.00 v2018.08.09.00 v2018.08.06.00 v2018.07.30.00 v2018.07.23.00 v2018.07.16.00 v2018.07.09.00 v2018.07.02.00 v2018.06.25.00 v2018.06.18.00 v2018.06.11.00 v2018.06.04.00 v2018.05.28.00 v2018.05.21.00 v2018.05.14.00 v2018.05.07.00 v2018.04.30.00 v2018.04.23.00 v2018.04.16.00 v2018.04.09.00 v2018.04.02.00 v2018.03.26.00 v2018.03.19.00 v2018.03.12.00 v2018.03.05.00 v2018.02.26.00 v2018.02.19.00 v2018.02.12.00 v2018.02.05.00 v2018.01.29.00 v2018.01.22.00 v2018.01.15.00 v2018.01.08.00 v2018.01.01.00 v2017.12.25.00 v2017.12.18.00 v2017.12.11.00
No related merge requests found
......@@ -280,6 +280,15 @@ inline exception_wrapper exception_wrapper::SharedPtr::get_exception_ptr_(
return that->sptr_.ptr_->get_exception_ptr_();
}
template <class Ex, typename... As>
inline exception_wrapper::exception_wrapper(
ThrownTag,
in_place_type_t<Ex>,
As&&... as)
: eptr_{std::make_exception_ptr(Ex(std::forward<As>(as)...)),
reinterpret_cast<std::uintptr_t>(std::addressof(typeid(Ex))) + 1u},
vptr_(&ExceptionPtr::ops_) {}
template <class Ex, typename... As>
inline exception_wrapper::exception_wrapper(
OnHeapTag,
......
......@@ -235,16 +235,20 @@ class exception_wrapper final {
Ex const& as() const noexcept;
};
struct ThrownTag {};
struct InSituTag {};
struct OnHeapTag {};
template <class T>
using PlacementOf = _t<std::conditional<
!IsStdException<T>::value,
ThrownTag,
_t<std::conditional<
sizeof(T) <= sizeof(Buffer::Storage) &&
alignof(T) <= alignof(Buffer::Storage) &&
noexcept(T(std::declval<T&&>())),
InSituTag,
OnHeapTag>>;
OnHeapTag>>>>;
static std::exception const* as_exception_or_null_(std::exception const& ex);
static std::exception const* as_exception_or_null_(AnyException);
......@@ -278,6 +282,7 @@ class exception_wrapper final {
template <class Ex>
struct InPlace {
static_assert(IsStdException<Ex>::value, "only deriving std::exception");
static void copy_(exception_wrapper const* from, exception_wrapper* to);
static void move_(exception_wrapper* from, exception_wrapper* to);
static void delete_(exception_wrapper* that);
......@@ -306,6 +311,7 @@ class exception_wrapper final {
};
template <class Ex>
struct Impl final : public Base {
static_assert(IsStdException<Ex>::value, "only deriving std::exception");
Ex ex_;
Impl() = default;
template <typename... As>
......@@ -334,6 +340,9 @@ class exception_wrapper final {
};
VTable const* vptr_{&uninit_};
template <class Ex, typename... As>
exception_wrapper(ThrownTag, in_place_type_t<Ex>, As&&... as);
template <class Ex, typename... As>
exception_wrapper(OnHeapTag, in_place_type_t<Ex>, As&&... as);
......
......@@ -254,6 +254,7 @@ TEST(ExceptionWrapper, with_shared_ptr_test) {
EXPECT_EQ(typeid(std::runtime_error), ew.type());
EXPECT_NE(nullptr, ew.get_exception());
EXPECT_NE(nullptr, ew.get_exception<std::exception>());
EXPECT_STREQ("foo", ew.get_exception<std::exception>()->what());
EXPECT_EQ(nullptr, ew.get_exception<int>());
EXPECT_FALSE(ew.has_exception_ptr());
EXPECT_NE(nullptr, ew.to_exception_ptr());
......@@ -286,6 +287,7 @@ TEST(ExceptionWrapper, with_exception_ptr_exn_test) {
EXPECT_EQ(typeid(std::runtime_error), ew.type());
EXPECT_NE(nullptr, ew.get_exception());
EXPECT_NE(nullptr, ew.get_exception<std::exception>());
EXPECT_STREQ("foo", ew.get_exception<std::exception>()->what());
EXPECT_EQ(nullptr, ew.get_exception<int>());
EXPECT_TRUE(ew.has_exception_ptr());
EXPECT_EQ(ep, ew.to_exception_ptr());
......@@ -318,6 +320,7 @@ TEST(ExceptionWrapper, with_exception_ptr_any_test) {
EXPECT_EQ(nullptr, ew.get_exception());
EXPECT_EQ(nullptr, ew.get_exception<std::exception>());
EXPECT_NE(nullptr, ew.get_exception<int>());
EXPECT_EQ(12, *ew.get_exception<int>());
EXPECT_TRUE(ew.has_exception_ptr());
EXPECT_EQ(ep, ew.to_exception_ptr());
EXPECT_TRUE(ew.has_exception_ptr());
......@@ -348,7 +351,8 @@ TEST(ExceptionWrapper, with_non_std_exception_test) {
EXPECT_EQ(nullptr, ew.get_exception());
EXPECT_EQ(nullptr, ew.get_exception<std::exception>());
EXPECT_NE(nullptr, ew.get_exception<int>());
EXPECT_FALSE(ew.has_exception_ptr());
EXPECT_EQ(42, *ew.get_exception<int>());
EXPECT_TRUE(ew.has_exception_ptr());
EXPECT_EQ("int", ew.class_name());
EXPECT_EQ("int", ew.what());
EXPECT_NE(nullptr, ew.to_exception_ptr());
......@@ -381,6 +385,7 @@ TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) {
EXPECT_EQ(nullptr, ew.get_exception());
EXPECT_EQ(nullptr, ew.get_exception<std::exception>());
EXPECT_NE(nullptr, ew.get_exception<int>());
EXPECT_EQ(12, *ew.get_exception<int>());
EXPECT_EQ(ep, ew.to_exception_ptr());
EXPECT_EQ("<unknown exception>", ew.class_name()); // because concrete type is
// erased
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment