From e24ddb6027b6495a81c95133cfb6812d6090cd32 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 29 Dec 2021 12:24:45 -0500 Subject: [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 --- libcxx/include/__functional/function.h | 5 ++-- .../func.wrap/func.wrap.func/addressof.pass.cpp | 32 ++++++++++++++++++++++ .../func.wrap.func/robust_against_adl.pass.cpp | 10 +++++-- 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/addressof.pass.cpp 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 +// +//===----------------------------------------------------------------------===// + +// + +// class function + +// 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 +#include + +#include "operator_hijacker.h" + +struct TrapAddressof : operator_hijacker { + int operator()() const { return 1; } +}; + +int main(int, char**) { + std::function 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 struct Holder { T t; }; + typedef Holder *Ptr; +template +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 f(no_args); f(); std::function g(one_arg); g(x); std::function h(one_arg_void); h(x); + std::function i(Callable>{}); return 0; } -- cgit v1.2.1