Author: eugenis Date: Wed Feb 10 15:53:28 2016 New Revision: 260441 URL: http://llvm.org/viewvc/llvm-project?rev=260441&view=rev Log: Fix invalid casts in <functional>.
static_cast of a pointer to object before the start of the object's lifetime has undefined behavior. This code triggers CFI warnings. This change replaces C-style casts with reinterpret_cast, which is fine per the standard, add applies an attribute to silence CFI (which barks on reinterpret_cast, too). Modified: libcxx/trunk/include/__config libcxx/trunk/include/functional Modified: libcxx/trunk/include/__config URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=260441&r1=260440&r2=260441&view=diff ============================================================================== --- libcxx/trunk/include/__config (original) +++ libcxx/trunk/include/__config Wed Feb 10 15:53:28 2016 @@ -180,6 +180,12 @@ # endif #endif // !defined(_LIBCPP_LITTLE_ENDIAN) || !defined(_LIBCPP_BIG_ENDIAN) +#if __has_attribute(__no_sanitize__) +#define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) +#else +#define _LIBCPP_NO_CFI +#endif + #ifdef _WIN32 // only really useful for a DLL Modified: libcxx/trunk/include/functional URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=260441&r1=260440&r2=260441&view=diff ============================================================================== --- libcxx/trunk/include/functional (original) +++ libcxx/trunk/include/functional Wed Feb 10 15:53:28 2016 @@ -1564,6 +1564,10 @@ class _LIBCPP_TYPE_VIS_ONLY function<_Rp typename aligned_storage<3*sizeof(void*)>::type __buf_; __base* __f_; + _LIBCPP_NO_CFI static __base *__as_base(void *p) { + return reinterpret_cast<__base*>(p); + } + template <class _Fp, bool = !is_same<_Fp, function>::value && __invokable<_Fp&, _ArgTypes...>::value> struct __callable; @@ -1660,9 +1664,9 @@ function<_Rp(_ArgTypes...)>::function(co { if (__f.__f_ == 0) __f_ = 0; - else if (__f.__f_ == (const __base*)&__f.__buf_) + else if ((void *)__f.__f_ == &__f.__buf_) { - __f_ = (__base*)&__buf_; + __f_ = __as_base(&__buf_); __f.__f_->__clone(__f_); } else @@ -1676,9 +1680,9 @@ function<_Rp(_ArgTypes...)>::function(al { if (__f.__f_ == 0) __f_ = 0; - else if (__f.__f_ == (const __base*)&__f.__buf_) + else if ((void *)__f.__f_ == &__f.__buf_) { - __f_ = (__base*)&__buf_; + __f_ = __as_base(&__buf_); __f.__f_->__clone(__f_); } else @@ -1690,9 +1694,9 @@ function<_Rp(_ArgTypes...)>::function(fu { if (__f.__f_ == 0) __f_ = 0; - else if (__f.__f_ == (__base*)&__f.__buf_) + else if ((void *)__f.__f_ == &__f.__buf_) { - __f_ = (__base*)&__buf_; + __f_ = __as_base(&__buf_); __f.__f_->__clone(__f_); } else @@ -1709,9 +1713,9 @@ function<_Rp(_ArgTypes...)>::function(al { if (__f.__f_ == 0) __f_ = 0; - else if (__f.__f_ == (__base*)&__f.__buf_) + else if ((void *)__f.__f_ == &__f.__buf_) { - __f_ = (__base*)&__buf_; + __f_ = __as_base(&__buf_); __f.__f_->__clone(__f_); } else @@ -1736,8 +1740,7 @@ function<_Rp(_ArgTypes...)>::function(_F typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_ArgTypes...)> _FF; if (sizeof(_FF) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) { - __f_ = (__base*)&__buf_; - ::new (__f_) _FF(_VSTD::move(__f)); + __f_ = ::new((void*)&__buf_) _FF(_VSTD::move(__f)); } else { @@ -1766,8 +1769,7 @@ function<_Rp(_ArgTypes...)>::function(al if (sizeof(_FF) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value && is_nothrow_copy_constructible<_Ap>::value) { - __f_ = (__base*)&__buf_; - ::new (__f_) _FF(_VSTD::move(__f), _Alloc(__a)); + __f_ = ::new((void*)&__buf_) _FF(_VSTD::move(__f), _Alloc(__a)); } else { @@ -1791,16 +1793,16 @@ template<class _Rp, class ..._ArgTypes> function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT { - if (__f_ == (__base*)&__buf_) + if ((void *)__f_ == &__buf_) __f_->destroy(); else if (__f_) __f_->destroy_deallocate(); __f_ = 0; if (__f.__f_ == 0) __f_ = 0; - else if (__f.__f_ == (__base*)&__f.__buf_) + else if ((void *)__f.__f_ == &__f.__buf_) { - __f_ = (__base*)&__buf_; + __f_ = __as_base(&__buf_); __f.__f_->__clone(__f_); } else @@ -1815,7 +1817,7 @@ template<class _Rp, class ..._ArgTypes> function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT { - if (__f_ == (__base*)&__buf_) + if ((void *)__f_ == &__buf_) __f_->destroy(); else if (__f_) __f_->destroy_deallocate(); @@ -1840,7 +1842,7 @@ function<_Rp(_ArgTypes...)>::operator=(_ template<class _Rp, class ..._ArgTypes> function<_Rp(_ArgTypes...)>::~function() { - if (__f_ == (__base*)&__buf_) + if ((void *)__f_ == &__buf_) __f_->destroy(); else if (__f_) __f_->destroy_deallocate(); @@ -1850,34 +1852,34 @@ template<class _Rp, class ..._ArgTypes> void function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT { - if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) + if ((void *)__f_ == &__buf_ && (void *)__f.__f_ == &__f.__buf_) { typename aligned_storage<sizeof(__buf_)>::type __tempbuf; - __base* __t = (__base*)&__tempbuf; + __base* __t = __as_base(&__tempbuf); __f_->__clone(__t); __f_->destroy(); __f_ = 0; - __f.__f_->__clone((__base*)&__buf_); + __f.__f_->__clone(__as_base(&__buf_)); __f.__f_->destroy(); __f.__f_ = 0; - __f_ = (__base*)&__buf_; - __t->__clone((__base*)&__f.__buf_); + __f_ = __as_base(&__buf_); + __t->__clone(__as_base(&__f.__buf_)); __t->destroy(); - __f.__f_ = (__base*)&__f.__buf_; + __f.__f_ = __as_base(&__f.__buf_); } - else if (__f_ == (__base*)&__buf_) + else if ((void *)__f_ == &__buf_) { - __f_->__clone((__base*)&__f.__buf_); + __f_->__clone(__as_base(&__f.__buf_)); __f_->destroy(); __f_ = __f.__f_; - __f.__f_ = (__base*)&__f.__buf_; + __f.__f_ = __as_base(&__f.__buf_); } - else if (__f.__f_ == (__base*)&__f.__buf_) + else if ((void *)__f.__f_ == &__f.__buf_) { - __f.__f_->__clone((__base*)&__buf_); + __f.__f_->__clone(__as_base(&__buf_)); __f.__f_->destroy(); __f.__f_ = __f_; - __f_ = (__base*)&__buf_; + __f_ = __as_base(&__buf_); } else _VSTD::swap(__f_, __f.__f_); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits