[libcxx-commits] [libcxx] f3274a4 - Prepare libcxx and libcxxabi for pointer field protection.
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Mar 25 15:51:40 PDT 2026
Author: Peter Collingbourne
Date: 2026-03-25T15:51:35-07:00
New Revision: f3274a496c7f80ff95170c1f78fdad48f95e67bd
URL: https://github.com/llvm/llvm-project/commit/f3274a496c7f80ff95170c1f78fdad48f95e67bd
DIFF: https://github.com/llvm/llvm-project/commit/f3274a496c7f80ff95170c1f78fdad48f95e67bd.diff
LOG: Prepare libcxx and libcxxabi for pointer field protection.
Pointer field protection has the following characteristics:
- Pointer fields in RTTI types are unsigned. Signing these fields
is unnecessary because PFP is a mechanism for protecting the heap,
and the RTTI objects typically live in global variables. Therefore,
mark the fields with the no_field_protection to inhibit PFP for these
fields.
- libcxx's interim trivial relocatability implementation, which memcpy's
some non-trivially-copyable objects according to the value of a trait,
conflicts with PFP in tagged mode (in which the address of the pointer
is used as part of the pointer encoding) by causing such copies to
result in a crash in some cases where the object being copied includes
a pointer field. These copies are undefined behavior. Therefore, make
libcxx's trivially relocatable predicate simply return the value of
the trivially copyable trait when PFP in tagged mode is enabled, which
results in standards compliant behavior that is accommodated by PFP.
Reviewers: philnik777, fmayer, ldionne
Pull Request: https://github.com/llvm/llvm-project/pull/151651
Added:
Modified:
libcxx/include/__configuration/attributes.h
libcxx/include/__type_traits/is_trivially_relocatable.h
libcxx/include/typeinfo
libcxxabi/include/__cxxabi_config.h
libcxxabi/src/private_typeinfo.h
Removed:
################################################################################
diff --git a/libcxx/include/__configuration/attributes.h b/libcxx/include/__configuration/attributes.h
index 7322995701ba2..39683b7688d76 100644
--- a/libcxx/include/__configuration/attributes.h
+++ b/libcxx/include/__configuration/attributes.h
@@ -457,4 +457,10 @@
# define _LIBCPP_DEPRECATED_WITH_CHAR8_T
#endif
+#if __has_cpp_attribute(_Clang::__no_field_protection__)
+# define _LIBCPP_DISABLE_POINTER_FIELD_PROTECTION [[_Clang::__no_field_protection__]]
+#else
+# define _LIBCPP_DISABLE_POINTER_FIELD_PROTECTION
+#endif
+
#endif // _LIBCPP___CONFIGURATION_ATTRIBUTES_H
diff --git a/libcxx/include/__type_traits/is_trivially_relocatable.h b/libcxx/include/__type_traits/is_trivially_relocatable.h
index 9b0e240de55f4..8f7c4ccd8a383 100644
--- a/libcxx/include/__type_traits/is_trivially_relocatable.h
+++ b/libcxx/include/__type_traits/is_trivially_relocatable.h
@@ -34,10 +34,14 @@ template <class _Tp, class = void>
struct __libcpp_is_trivially_relocatable : is_trivially_copyable<_Tp> {};
#endif
+// __trivially_relocatable on libc++'s builtin types does not currently return the right answer with PFP
+// in tagged mode, in which the address of the pointer is used as part of the pointer encoding.
+#if !defined(__POINTER_FIELD_PROTECTION_TAGGED__)
template <class _Tp>
struct __libcpp_is_trivially_relocatable<_Tp,
__enable_if_t<is_same<_Tp, typename _Tp::__trivially_relocatable>::value> >
: true_type {};
+#endif
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo
index f67d61e368087..7cc675ce59ae5 100644
--- a/libcxx/include/typeinfo
+++ b/libcxx/include/typeinfo
@@ -302,7 +302,7 @@ class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info
protected:
typedef __type_info_implementations::__impl __impl;
- __impl::__type_name_t __type_name;
+ _LIBCPP_DISABLE_POINTER_FIELD_PROTECTION __impl::__type_name_t __type_name;
_LIBCPP_HIDE_FROM_ABI explicit type_info(const char* __n) : __type_name(__impl::__string_to_type_name(__n)) {}
diff --git a/libcxxabi/include/__cxxabi_config.h b/libcxxabi/include/__cxxabi_config.h
index e4fd845b1fb35..6ec10e469387e 100644
--- a/libcxxabi/include/__cxxabi_config.h
+++ b/libcxxabi/include/__cxxabi_config.h
@@ -128,4 +128,10 @@
# define _LIBCXXABI_NOEXCEPT noexcept
#endif
+#if defined(__POINTER_FIELD_PROTECTION_ABI__)
+# define _LIBCXXABI_DISABLE_POINTER_FIELD_PROTECTION [[_Clang::__no_field_protection__]]
+#else
+# define _LIBCXXABI_DISABLE_POINTER_FIELD_PROTECTION
+#endif
+
#endif // ____CXXABI_CONFIG_H
diff --git a/libcxxabi/src/private_typeinfo.h b/libcxxabi/src/private_typeinfo.h
index 328a02edef5c1..e92dc332d986b 100644
--- a/libcxxabi/src/private_typeinfo.h
+++ b/libcxxabi/src/private_typeinfo.h
@@ -145,7 +145,7 @@ class _LIBCXXABI_TYPE_VIS __class_type_info : public __shim_type_info {
// Has one non-virtual public base class at offset zero
class _LIBCXXABI_TYPE_VIS __si_class_type_info : public __class_type_info {
public:
- const __class_type_info *__base_type;
+ _LIBCXXABI_DISABLE_POINTER_FIELD_PROTECTION const __class_type_info* __base_type;
_LIBCXXABI_HIDDEN virtual ~__si_class_type_info();
@@ -204,7 +204,7 @@ class _LIBCXXABI_TYPE_VIS __vmi_class_type_info : public __class_type_info {
class _LIBCXXABI_TYPE_VIS __pbase_type_info : public __shim_type_info {
public:
unsigned int __flags;
- const __shim_type_info *__pointee;
+ _LIBCXXABI_DISABLE_POINTER_FIELD_PROTECTION const __shim_type_info* __pointee;
enum __masks {
__const_mask = 0x1,
@@ -245,7 +245,7 @@ class _LIBCXXABI_TYPE_VIS __pointer_type_info : public __pbase_type_info {
class _LIBCXXABI_TYPE_VIS __pointer_to_member_type_info
: public __pbase_type_info {
public:
- const __class_type_info *__context;
+ _LIBCXXABI_DISABLE_POINTER_FIELD_PROTECTION const __class_type_info* __context;
_LIBCXXABI_HIDDEN virtual ~__pointer_to_member_type_info();
_LIBCXXABI_HIDDEN virtual bool can_catch(const __shim_type_info *,
More information about the libcxx-commits
mailing list