From a98e51a869955aef29c3057c8c539ad59829b51f Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 23 Jun 2025 13:11:17 +0100 Subject: [PATCH] b-tree: fix incorrect copy bounds and pointer swaps --- src/b-tree.c | 64 +++++++++++++++++++++++++++++++++++++++++----------- src/b-tree.h | 1 + 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/b-tree.c b/src/b-tree.c index 3179962..03d2088 100644 --- a/src/b-tree.c +++ b/src/b-tree.c @@ -1,5 +1,7 @@ #include "b-tree.h" +#include "bin.h" + #include #include #include @@ -180,21 +182,33 @@ static void node_shift_entries( unsigned long count = nr_entries - shift_from; for (unsigned long i = 0; i < count; i++) { - unsigned long from = (src + count - 1) - i; - unsigned long to = (dest + count - 1) - i; + unsigned long from, to; + if (shift_by > 0) { + from = (src + count - 1) - i; + to = (dest + count - 1) - i; + } else { + from = src + i; + to = dest + i; + } + b_tree_node_entry *entry = node_get_entry(tree, node, from); node_set_entry(tree, node, to, entry); } +#if 0 if (shift_by < 0) { - dest = nr_entries + shift_by; + if (src < dest + count) { + src = dest + count; + } count = labs(shift_by); } else { - dest = src; count = shift_by; } - node_kill_entry(tree, node, dest); + for (size_t i = 0; i < count; i++) { + node_kill_entry(tree, node, src + i); + } +#endif } static void node_shift_children( @@ -221,19 +235,30 @@ static void node_shift_children( } for (unsigned long i = 0; i < count; i++) { - unsigned long child = node_get_child(tree, node, src + i); - node_set_child(tree, node, dest + i, child); + unsigned long from, to; + if (shift_by > 0) { + from = (src + count - 1) - i; + to = (dest + count - 1) - i; + } else { + from = src + i; + to = dest + i; + } + + unsigned long child = node_get_child(tree, node, from); + node_set_child(tree, node, to, child); } if (shift_by < 0) { - dest = nr_entries + 1 + shift_from; count = labs(shift_by); } else { - dest = src; count = shift_by; } - node_set_child(tree, node, dest, B_TREE_INVALID_PTR); +#if 0 + for (size_t i = 0; i < count; i++) { + node_set_child(tree, node, src + i, B_TREE_INVALID_PTR); + } +#endif } static void node_move_entries( @@ -367,12 +392,22 @@ static int node_is_leaf(struct b_tree *tree, b_tree_node *node) static void node_init(struct b_tree *tree, b_tree_node *out) { + if (!tree->tree_ops->node_init) { + abort(); + } + + tree->tree_ops->node_init(tree, out); + +#if 0 memset(out, 0x0, tree->tree_node_size); for (unsigned int i = 0; i < tree->tree_order; i++) { node_set_child(tree, out, i, B_TREE_INVALID_PTR); } +#endif } +extern const struct b_tree_ops chunk_table_ops; + int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) { int depth = 0; @@ -449,7 +484,8 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) nr_entries = node_get_nr_entries(tree, next); if (nr_entries < tree->tree_order - 1) { /* swap current and next pointers. */ - + SWAP(b_tree_node *, current, next); + SWAP(long, current_id, next_id); leaf = node_is_leaf(tree, current); depth++; @@ -463,6 +499,7 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) be moved to `current`. `n3` will become the right sibling of `next` */ + b_tree_node *n3 = cache_alloc_node(tree); node_init(tree, n3); @@ -511,8 +548,9 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) current = n3; current_id = n3_id; } else { + cache_free_node(tree, n3); SWAP(b_tree_node *, current, next); - current_id = next_id; + SWAP(long, current_id, next_id); } depth++; @@ -575,7 +613,7 @@ int b_tree_get(struct b_tree *tree, b_tree_node_entry *to_get) /* swap current and next pointers. */ SWAP(b_tree_node *, current, next); - current_id = next_id; + SWAP(long, current_id, next_id); nr_entries = node_get_nr_entries(tree, current); } diff --git a/src/b-tree.h b/src/b-tree.h index a75b3fc..ea826c4 100644 --- a/src/b-tree.h +++ b/src/b-tree.h @@ -23,6 +23,7 @@ struct b_tree_ops { const b_tree_node *); long (*tree_alloc_node)(struct b_tree *); + void (*node_init)(struct b_tree *, b_tree_node *); unsigned long (*node_get_nr_entries)(struct b_tree *, b_tree_node *); void (*node_set_nr_entries)( struct b_tree *,