mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 21:53:12 +08:00
[libc++] Guard call_once against operator hijacking. (#128054)
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <__config>
|
||||
#include <__functional/invoke.h>
|
||||
#include <__memory/addressof.h>
|
||||
#include <__memory/shared_count.h> // __libcpp_acquire_load
|
||||
#include <__tuple/tuple_indices.h>
|
||||
#include <__tuple/tuple_size.h>
|
||||
@@ -128,7 +129,7 @@ inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable&& __fun
|
||||
typedef tuple<_Callable&&, _Args&&...> _Gp;
|
||||
_Gp __f(std::forward<_Callable>(__func), std::forward<_Args>(__args)...);
|
||||
__call_once_param<_Gp> __p(__f);
|
||||
std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
|
||||
std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<_Gp>));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +139,7 @@ template <class _Callable>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable& __func) {
|
||||
if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {
|
||||
__call_once_param<_Callable> __p(__func);
|
||||
std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
|
||||
std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<_Callable>));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +147,7 @@ template <class _Callable>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, const _Callable& __func) {
|
||||
if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {
|
||||
__call_once_param<const _Callable> __p(__func);
|
||||
std::__call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
|
||||
std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<const _Callable>));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
// UNSUPPORTED: no-threads
|
||||
|
||||
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
|
||||
|
||||
// <mutex>
|
||||
|
||||
// struct once_flag;
|
||||
@@ -21,6 +23,7 @@
|
||||
|
||||
#include "make_test_thread.h"
|
||||
#include "test_macros.h"
|
||||
#include "operator_hijacker.h"
|
||||
|
||||
typedef std::chrono::milliseconds ms;
|
||||
|
||||
@@ -253,7 +256,19 @@ int main(int, char**)
|
||||
std::call_once(f2, std::move(rq));
|
||||
assert(rq.rv_called == 1);
|
||||
}
|
||||
{
|
||||
std::once_flag flag;
|
||||
auto f = [](const operator_hijacker&) {};
|
||||
std::call_once(flag, f, operator_hijacker{});
|
||||
}
|
||||
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
return 0;
|
||||
{
|
||||
std::once_flag flag;
|
||||
operator_hijacker f;
|
||||
std::call_once(flag, f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
struct operator_hijacker {
|
||||
TEST_CONSTEXPR bool operator<(const operator_hijacker&) const { return true; }
|
||||
TEST_CONSTEXPR bool operator==(const operator_hijacker&) const { return true; }
|
||||
TEST_CONSTEXPR int operator()() const { return 42; }
|
||||
|
||||
template <typename T>
|
||||
friend void operator&(T&&) = delete;
|
||||
|
||||
Reference in New Issue
Block a user