diff options
author | Louis Dionne <ldionne.2@gmail.com> | 2021-12-29 12:24:45 -0500 |
---|---|---|
committer | Louis Dionne <ldionne.2@gmail.com> | 2022-01-04 12:31:45 -0500 |
commit | e24ddb6027b6495a81c95133cfb6812d6090cd32 (patch) | |
tree | 139613522a17bd8dd697e7c0f76afbc482ec6adc | |
parent | 0b09313cd53316eacbdc5e98d4ef00bef2c41d02 (diff) | |
download | llvm-e24ddb6027b6495a81c95133cfb6812d6090cd32.tar.gz |
[libc++] Use std::addressof in std::function::target
This guards against hostile overloads of operator&. Thanks to Peter Dimov
for the report in https://github.com/boostorg/lambda/issues/24.
Differential Revision: https://reviews.llvm.org/D116380
3 files changed, 43 insertions, 4 deletions
diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h index 8336d85adf2e..b6d383ce8459 100644 --- a/libcxx/include/__functional/function.h +++ b/libcxx/include/__functional/function.h @@ -16,6 +16,7 @@ #include <__functional/invoke.h> #include <__functional/unary_function.h> #include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> #include <__memory/shared_ptr.h> @@ -360,7 +361,7 @@ const void* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT { if (__ti == typeid(_Fp)) - return &__f_.__target(); + return _VSTD::addressof(__f_.__target()); return nullptr; } @@ -1392,7 +1393,7 @@ const void* __func<_Fp, _Alloc, _Rp()>::target(const type_info& __ti) const { if (__ti == typeid(_Fp)) - return &__f_.first(); + return _VSTD::addressof(__f_.first()); return (const void*)0; } diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/addressof.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/addressof.pass.cpp new file mode 100644 index 000000000000..d18f9c45f71f --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/addressof.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <functional> + +// class function<R(ArgTypes...)> + +// This test runs in C++03, but we have deprecated using std::function in C++03. +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS + +// Make sure we can use std::function with a type that has a hostile overload +// of operator&(). + +#include <functional> +#include <cassert> + +#include "operator_hijacker.h" + +struct TrapAddressof : operator_hijacker { + int operator()() const { return 1; } +}; + +int main(int, char**) { + std::function<int()> f = TrapAddressof(); + assert(f() == 1); + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp index 23e477619037..3c0851e4eebe 100644 --- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp @@ -27,8 +27,14 @@ struct Incomplete; template<class T> struct Holder { T t; }; + typedef Holder<Incomplete> *Ptr; +template<class T> +struct Callable { + void operator()() const { } +}; + Ptr no_args() { return nullptr; } Ptr one_arg(Ptr p) { return p; } Ptr two_args(Ptr p, Ptr) { return p; } @@ -37,11 +43,11 @@ Ptr four_args(Ptr p, Ptr, Ptr, Ptr) { return p; } void one_arg_void(Ptr) { } -int main(int, char**) -{ +int main(int, char**) { Ptr x = nullptr; std::function<Ptr()> f(no_args); f(); std::function<Ptr(Ptr)> g(one_arg); g(x); std::function<void(Ptr)> h(one_arg_void); h(x); + std::function<void()> i(Callable<Holder<Incomplete>>{}); return 0; } |