[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
This commit is contained in:
Louis Dionne 2021-12-29 12:24:45 -05:00
parent 0b09313cd5
commit e24ddb6027
3 changed files with 43 additions and 4 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}