https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119151

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|[13/14/15 Regression]       |[13/14 Regression]
                   |unwind-dw2-btree maintains  |unwind-dw2-btree maintains
                   |separators wrong            |separators wrong

--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Should be now fixed on the trunk so far, thanks for the detailed report.

As for the issues you mention even with the patch, there are a few spots I'm a
little bit worried about but haven't tried to come up with a testcase which
would prove it actually can happen.

So, perhaps try:
--- a/libgcc/unwind-dw2-btree.h 2025-03-10 10:33:53.046835685 +0100
+++ b/libgcc/unwind-dw2-btree.h 2025-03-10 10:44:13.689263848 +0100
@@ -321,6 +321,8 @@ btree_node_update_separator_after_split
     n->content.children[index] = n->content.children[index - 1];
   n->content.children[slot].separator = new_separator;
   n->content.children[slot + 1].child = new_right;
+  if (new_separator >= n->content.children[slot + 1].separator)
+    __builtin_abort ();
   n->entry_count++;
 }

@@ -566,6 +568,8 @@ btree_merge_node (struct btree *t, unsig
       right_node = parent->content.children[left_slot + 1].child;
       btree_node_lock_exclusive (left_node);
     }
+  if (btree_node_is_inner (left_node) != btree_node_is_inner (right_node))
+    __builtin_abort ();

   // Can we merge both nodes into one node?
   unsigned total_count = left_node->entry_count + right_node->entry_count;
@@ -766,7 +770,12 @@ btree_insert (struct btree *t, uintptr_t
        // lookup.  Update the separator now.  Assumption that users
        // ensure no overlapping registered ranges, there should be no
        // current entry for any address in the range.  See PR119151.
-       fence = iter->content.children[slot].separator = base + size - 1;
+       {
+         fence = iter->content.children[slot].separator = base + size - 1;
+         if (slot + 1 < iter->entry_count
+             && fence >= iter->content.children[slot + 1].separator)
+           __builtin_abort ();
+       }
       iter = iter->content.children[slot].child;
       btree_node_lock_exclusive (iter);
     }
on top of the GCC trunk version.  The first and last hunk attempt to verify
that we never increase the separator too much relative to the following
separator (if any) and the middle hunk is I'm worried nothing checks on merging
nodes if there would be one leaf and one inner node being merged (I don't see
what would prevent there, earlier btree_remove can result in children of one of
the inner nodes to be merged into the parent, turning the parent into leaf, and
I wonder if the neighbouring node could at that point still be inner and later
on perhaps something removed from that neighbouring node; though I guess if
that happens, there could be worse crashes).

Reply via email to