[libcxx-commits] [libcxxabi] [libc++abi] Handle null pointer-to-object: Issue #64593 (PR #68076)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 3 01:27:11 PDT 2023


github-actions[bot] wrote:


<!--LLVM CODE FORMAT COMMENT: {clang-format}-->

:warning: C/C++ code formatter, clang-format found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
git-clang-format --diff 864beb179280f9b2e81b303462dfff90c283c8be 459ea8dcdc722391de3b17a20f14fb8022411c70 -- libcxxabi/test/catch_null_pointer_to_object_pr64953.pass.cpp libcxxabi/src/private_typeinfo.cpp libcxxabi/src/private_typeinfo.h
``````````

</details>

<details>
<summary>
View the diff from clang-format here.
</summary>

``````````diff
diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp
index 197ea2ab8..34c340fdd 100644
--- a/libcxxabi/src/private_typeinfo.cpp
+++ b/libcxxabi/src/private_typeinfo.cpp
@@ -161,15 +161,11 @@ const void* dyn_cast_to_derived(const void* static_ptr,
     // Fallback to the slow path to check that static_type is a public
     //   base type of dynamic_type.
     // Using giant short cut.  Add that information to info.
-    __dynamic_cast_info info = {
-        dst_type,
-        static_ptr,
-        static_type,
-        src2dst_offset,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        1,  // number_of_dst_type
-        false, false, false, true
-    };
+    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset,
+                                0,        0,          0,           0,
+                                0,        0,          0,           0,
+                                1, // number_of_dst_type
+                                false,    false,      false,       true};
     // Do the  search
     dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
 #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
@@ -188,13 +184,8 @@ const void* dyn_cast_to_derived(const void* static_ptr,
                     "should have public visibility. At least one of them is hidden. %s"
                     ", %s.\n", static_type->name(), dst_type->name());
         // Redo the search comparing type_info's using strcmp
-        info = {
-            dst_type,
-            static_ptr,
-            static_type,
-            src2dst_offset,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false, true
-        };
+        info = {dst_type, static_ptr, static_type, src2dst_offset, 0,     0,     0,   0, 0, 0,
+                0,        0,          0,           false,          false, false, true};
         info.number_of_dst_type = 1;
         dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
     }
@@ -233,15 +224,23 @@ const void* dyn_cast_try_downcast(const void* static_ptr,
     }
 
     // Try to search a path from dynamic_type to dst_type.
-    __dynamic_cast_info dynamic_to_dst_info = {
-        dynamic_type,
-        dst_ptr_to_static,
-        dst_type,
-        src2dst_offset,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        1,  // number_of_dst_type
-        false, false, false, true
-    };
+    __dynamic_cast_info dynamic_to_dst_info = {dynamic_type,
+                                               dst_ptr_to_static,
+                                               dst_type,
+                                               src2dst_offset,
+                                               0,
+                                               0,
+                                               0,
+                                               0,
+                                               0,
+                                               0,
+                                               0,
+                                               0,
+                                               1, // number_of_dst_type
+                                               false,
+                                               false,
+                                               false,
+                                               true};
     dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
     if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
         // We have found at least one path from dynamic_ptr to dst_ptr. The
@@ -262,13 +261,8 @@ const void* dyn_cast_slow(const void* static_ptr,
     // Not using giant short cut.  Do the search
 
     // Initialize info struct for this search.
-    __dynamic_cast_info info = {
-        dst_type,
-        static_ptr,
-        static_type,
-        src2dst_offset,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false, true
-    };
+    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0,     0,     0,   0, 0, 0,
+                                0,        0,          0,           false,          false, false, true};
 
     dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
 #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
@@ -288,13 +282,8 @@ const void* dyn_cast_slow(const void* static_ptr,
                             "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
                     dst_type->name());
         // Redo the search comparing type_info's using strcmp
-        info = {
-            dst_type,
-            static_ptr,
-            static_type,
-            src2dst_offset,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false, true
-        };
+        info = {dst_type, static_ptr, static_type, src2dst_offset, 0,     0,     0,   0, 0, 0,
+                0,        0,          0,           false,          false, false, true};
         dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
     }
 #endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
@@ -482,9 +471,8 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,
     if (thrown_class_type == 0)
         return false;
     // bullet 2
-    assert (adjustedPtr && "catching a class without an object?");
-    __dynamic_cast_info info = {thrown_class_type, 0, this,
-                                -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true};
+    assert(adjustedPtr && "catching a class without an object?");
+    __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true};
     info.number_of_dst_type = 1;
     thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, nullptr, public_path);
     if (info.path_dst_ptr_to_static_ptr == public_path)
@@ -515,123 +503,90 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,
 // different offset (adjustedPtr) from any previously recorded, this indicates
 // an ambiguous case within the virtual base.
 
-void
-__class_type_info::process_found_base_class(__dynamic_cast_info* info,
-                                               void* adjustedPtr,
-                                               const void* virtualBase,
-                                               int path_below) const
-{
-    if (info->number_to_static_ptr == 0)
-    {
-        // First time here
-        info->dst_ptr_leading_to_static_ptr = adjustedPtr;
-        info->path_dst_ptr_to_static_ptr = path_below;
-        // re-purpose this pointer.
-        info->dst_ptr_not_leading_to_static_ptr = virtualBase;
-        info->number_to_static_ptr = 1;
-    }
-    else if (info->dst_ptr_not_leading_to_static_ptr == virtualBase &&
-             info->dst_ptr_leading_to_static_ptr == adjustedPtr)
-    {
-        // We've been here before.  Update path to "most public"
-        if (info->path_dst_ptr_to_static_ptr == not_public_path)
-            info->path_dst_ptr_to_static_ptr = path_below;
-    }
-    else
-    {
-        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
-        //   to a static_type
-        info->number_to_static_ptr += 1;
-        info->path_dst_ptr_to_static_ptr = not_public_path;
-        info->search_done = true;
-    }
+void __class_type_info::process_found_base_class(__dynamic_cast_info* info, void* adjustedPtr, const void* virtualBase,
+                                                 int path_below) const {
+  if (info->number_to_static_ptr == 0) {
+    // First time here
+    info->dst_ptr_leading_to_static_ptr = adjustedPtr;
+    info->path_dst_ptr_to_static_ptr = path_below;
+    // re-purpose this pointer.
+    info->dst_ptr_not_leading_to_static_ptr = virtualBase;
+    info->number_to_static_ptr = 1;
+  } else if (info->dst_ptr_not_leading_to_static_ptr == virtualBase &&
+             info->dst_ptr_leading_to_static_ptr == adjustedPtr) {
+    // We've been here before.  Update path to "most public"
+    if (info->path_dst_ptr_to_static_ptr == not_public_path)
+      info->path_dst_ptr_to_static_ptr = path_below;
+  } else {
+    // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
+    //   to a static_type
+    info->number_to_static_ptr += 1;
+    info->path_dst_ptr_to_static_ptr = not_public_path;
+    info->search_done = true;
+  }
 }
 
-void
-__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
-                                               void* adjustedPtr,
-                                               const void* virtualBase,
-                                               int path_below) const
-{
-    if (is_equal(this, info->static_type, false))
-        process_found_base_class(info, adjustedPtr, virtualBase, path_below);
+void __class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, void* adjustedPtr,
+                                                    const void* virtualBase, int path_below) const {
+  if (is_equal(this, info->static_type, false))
+    process_found_base_class(info, adjustedPtr, virtualBase, path_below);
 }
 
-void
-__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
-                                                  void* adjustedPtr,
-                                                  const void* virtualBase,
-                                                  int path_below) const
-{
-    if (is_equal(this, info->static_type, false))
-        process_found_base_class(info, adjustedPtr, virtualBase, path_below);
-    else
-        __base_type->has_unambiguous_public_base(info, adjustedPtr, virtualBase, path_below);
+void __si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, void* adjustedPtr,
+                                                       const void* virtualBase, int path_below) const {
+  if (is_equal(this, info->static_type, false))
+    process_found_base_class(info, adjustedPtr, virtualBase, path_below);
+  else
+    __base_type->has_unambiguous_public_base(info, adjustedPtr, virtualBase, path_below);
 }
 
-void
-__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
-                                                    void* adjustedPtr,
-                                                    const void* virtualBase,
-                                                    int path_below) const
-{
-    bool is_virtual = __offset_flags & __virtual_mask;
-    ptrdiff_t offset_to_base = 0;
-    if (info->have_object)
-    {
-        /* We have an object to inspect, we can look through its vtables to
+void __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, void* adjustedPtr,
+                                                         const void* virtualBase, int path_below) const {
+  bool is_virtual = __offset_flags & __virtual_mask;
+  ptrdiff_t offset_to_base = 0;
+  if (info->have_object) {
+    /* We have an object to inspect, we can look through its vtables to
            find the layout.  */
-        offset_to_base = __offset_flags >> __offset_shift;
-        if (is_virtual)
-        {
-            const char* vtable = *static_cast<const char*const*>(adjustedPtr);
-            offset_to_base = update_offset_to_base(vtable, offset_to_base);
-        }
-    } else if (! is_virtual) {
-        /* We have no object - so we cannot use it for determining layout when
+    offset_to_base = __offset_flags >> __offset_shift;
+    if (is_virtual) {
+      const char* vtable = *static_cast<const char* const*>(adjustedPtr);
+      offset_to_base = update_offset_to_base(vtable, offset_to_base);
+    }
+  } else if (!is_virtual) {
+    /* We have no object - so we cannot use it for determining layout when
            we have a virtual base (since we cannot indirect through the vtable
            to find the actual object offset).  However, for non-virtual bases,
            we can pretend to have an object based at '0' */
-        offset_to_base = __offset_flags >> __offset_shift;
-    } else {
-      // no object to inspect, and the next base is virtual.
-      // we want to update virtualBase to the new innermost virtual base.
-      // using the pointer to the typeinfo name as a key.
-      virtualBase = static_cast<const void*>(__base_type->name ());
-      // .. and reset the pointer.
-      adjustedPtr = nullptr;
-    }
-    __base_type->has_unambiguous_public_base(
-            info,
-            static_cast<char*>(adjustedPtr) + offset_to_base,
-            virtualBase,
-            (__offset_flags & __public_mask) ? path_below : not_public_path);
+    offset_to_base = __offset_flags >> __offset_shift;
+  } else {
+    // no object to inspect, and the next base is virtual.
+    // we want to update virtualBase to the new innermost virtual base.
+    // using the pointer to the typeinfo name as a key.
+    virtualBase = static_cast<const void*>(__base_type->name());
+    // .. and reset the pointer.
+    adjustedPtr = nullptr;
+  }
+  __base_type->has_unambiguous_public_base(info, static_cast<char*>(adjustedPtr) + offset_to_base, virtualBase,
+                                           (__offset_flags & __public_mask) ? path_below : not_public_path);
 }
 
-void
-__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
-                                                   void* adjustedPtr,
-                                                   const void* virtualBase,
-                                                   int path_below) const
-{
-    if (is_equal(this, info->static_type, false))
-        process_found_base_class(info, adjustedPtr, virtualBase, path_below);
-    else
-    {
-        typedef const __base_class_type_info* Iter;
-        const Iter e = __base_info + __base_count;
-        Iter p = __base_info;
+void __vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, void* adjustedPtr,
+                                                        const void* virtualBase, int path_below) const {
+  if (is_equal(this, info->static_type, false))
+    process_found_base_class(info, adjustedPtr, virtualBase, path_below);
+  else {
+    typedef const __base_class_type_info* Iter;
+    const Iter e = __base_info + __base_count;
+    Iter p = __base_info;
+    p->has_unambiguous_public_base(info, adjustedPtr, virtualBase, path_below);
+    if (++p < e) {
+      do {
         p->has_unambiguous_public_base(info, adjustedPtr, virtualBase, path_below);
-        if (++p < e)
-        {
-            do
-            {
-                p->has_unambiguous_public_base(info, adjustedPtr, virtualBase, path_below);
-                if (info->search_done)
-                    break;
-            } while (++p < e);
-        }
+        if (info->search_done)
+          break;
+      } while (++p < e);
     }
+  }
 }
 
 // Handles bullet 1 for both pointers and member pointers
@@ -724,22 +679,21 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type,
     if (thrown_class_type == 0)
         return false;
     bool have_object = adjustedPtr != nullptr;
-    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1,
-                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			        have_object };
+    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                have_object};
     info.number_of_dst_type = 1;
     thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, nullptr, public_path);
     if (info.path_dst_ptr_to_static_ptr == public_path)
     {
-        // In the case of a thrown null pointer, we have no object but we might
-        // well have computed the offset to where a public sub-object would be.
-        // However, we do not want to return that offset to the user; we still
-        // want them to catch a null ptr.
-        if (have_object)
-            adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
-        else
-            adjustedPtr = nullptr;
-        return true;
+      // In the case of a thrown null pointer, we have no object but we might
+      // well have computed the offset to where a public sub-object would be.
+      // However, we do not want to return that offset to the user; we still
+      // want them to catch a null ptr.
+      if (have_object)
+        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
+      else
+        adjustedPtr = nullptr;
+      return true;
     }
     return false;
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/68076


More information about the libcxx-commits mailing list