Skip to content

Commit b6fa1d8

Browse files
yfeldblumfacebook-github-bot
authored andcommitted
fix make_exception_ptr_with under libc++
Summary: The `reinterpret_cast` to rvalue-ref triggered copy-construction under libc++, since `std::exception_ptr` has no move-constructor. This showed up as leaks reported by leak-sanitizer when using libc++. Since libstdc++ implements a separate move-constructor, it was unaffected. Originally landed as: {D74203904}. Reverted in: {D74256636}. There was another problem, where, under recent libc++ versions with `__cxa_init_primary_exception`, the code-path did not set the refcount. Whereas under prior libc++ versions, the code-path did set the refcount. So the original version of the diff fixed one leak under prior libc++ while adding a leak or a use-after-free under recent libc++. It would be a leak if no further increments or decrements were done on the refcount because no copies of the `exception_ptr` are made and the `exception_ptr` is not rethrown, but a use-after-free if the `exception_ptr` is copied or rethrown. Reviewed By: snarkmaster Differential Revision: D74269462 fbshipit-source-id: 7cc21581be88b4cbe26ee936d96807666249188a
1 parent f6d2ab1 commit b6fa1d8

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

folly/lang/Exception.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,15 @@ std::exception_ptr catch_current_exception_(Try&& t) noexcept {
698698
return catch_exception(static_cast<Try&&>(t), current_exception);
699699
}
700700

701+
template <typename Value>
702+
static std::exception_ptr make_exception_ptr_from_rep_(Value value) noexcept {
703+
static_assert(sizeof(std::exception_ptr) == sizeof(Value));
704+
static_assert(alignof(std::exception_ptr) == alignof(Value));
705+
std::exception_ptr ptr;
706+
std::memcpy(&ptr, &value, sizeof(value));
707+
return ptr;
708+
}
709+
701710
#if defined(__GLIBCXX__)
702711

703712
std::exception_ptr make_exception_ptr_with_(
@@ -711,7 +720,7 @@ std::exception_ptr make_exception_ptr_with_(
711720
scope_guard_ rollback{std::bind(abi::__cxa_free_exception, object)};
712721
arg.ctor(object, func);
713722
rollback.dismiss();
714-
return reinterpret_cast<std::exception_ptr&&>(object);
723+
return make_exception_ptr_from_rep_(object);
715724
});
716725
}
717726

@@ -735,6 +744,9 @@ std::exception_ptr make_exception_ptr_with_(
735744
auto type = const_cast<std::type_info*>(arg.type);
736745
#if _LIBCPP_VERSION >= 180000 && _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
737746
(void)abi::__cxa_init_primary_exception(object, type, arg.dtor);
747+
cxxabi_with_cxa_exception(object, [&](auto exception) {
748+
exception->referenceCount = 1;
749+
});
738750
#else
739751
cxxabi_with_cxa_exception(object, [&](auto exception) {
740752
#if defined(__FreeBSD__)
@@ -757,7 +769,7 @@ std::exception_ptr make_exception_ptr_with_(
757769
scope_guard_ rollback{std::bind(abi::__cxa_free_exception, object)};
758770
arg.ctor(object, func);
759771
rollback.dismiss();
760-
return reinterpret_cast<std::exception_ptr&&>(object);
772+
return make_exception_ptr_from_rep_(object);
761773
});
762774
}
763775

0 commit comments

Comments
 (0)