b-tree: fix incorrect copy bounds and pointer swaps

This commit is contained in:
2025-06-23 13:11:17 +01:00
parent 150b092d1b
commit a98e51a869
2 changed files with 52 additions and 13 deletions

View File

@@ -1,5 +1,7 @@
#include "b-tree.h" #include "b-tree.h"
#include "bin.h"
#include <assert.h> #include <assert.h>
#include <blue/core/queue.h> #include <blue/core/queue.h>
#include <stdlib.h> #include <stdlib.h>
@@ -180,21 +182,33 @@ static void node_shift_entries(
unsigned long count = nr_entries - shift_from; unsigned long count = nr_entries - shift_from;
for (unsigned long i = 0; i < count; i++) { for (unsigned long i = 0; i < count; i++) {
unsigned long from = (src + count - 1) - i; unsigned long from, to;
unsigned long to = (dest + count - 1) - i; 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); b_tree_node_entry *entry = node_get_entry(tree, node, from);
node_set_entry(tree, node, to, entry); node_set_entry(tree, node, to, entry);
} }
#if 0
if (shift_by < 0) { if (shift_by < 0) {
dest = nr_entries + shift_by; if (src < dest + count) {
src = dest + count;
}
count = labs(shift_by); count = labs(shift_by);
} else { } else {
dest = src;
count = shift_by; 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( static void node_shift_children(
@@ -221,19 +235,30 @@ static void node_shift_children(
} }
for (unsigned long i = 0; i < count; i++) { for (unsigned long i = 0; i < count; i++) {
unsigned long child = node_get_child(tree, node, src + i); unsigned long from, to;
node_set_child(tree, node, dest + i, child); 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) { if (shift_by < 0) {
dest = nr_entries + 1 + shift_from;
count = labs(shift_by); count = labs(shift_by);
} else { } else {
dest = src;
count = shift_by; 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( 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) 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); memset(out, 0x0, tree->tree_node_size);
for (unsigned int i = 0; i < tree->tree_order; i++) { for (unsigned int i = 0; i < tree->tree_order; i++) {
node_set_child(tree, out, i, B_TREE_INVALID_PTR); 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 b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put)
{ {
int depth = 0; 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); nr_entries = node_get_nr_entries(tree, next);
if (nr_entries < tree->tree_order - 1) { if (nr_entries < tree->tree_order - 1) {
/* swap current and next pointers. */ /* swap current and next pointers. */
SWAP(b_tree_node *, current, next);
SWAP(long, current_id, next_id);
leaf = node_is_leaf(tree, current); leaf = node_is_leaf(tree, current);
depth++; depth++;
@@ -463,6 +499,7 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put)
be moved to `current`. be moved to `current`.
`n3` will become the right sibling of `next` */ `n3` will become the right sibling of `next` */
b_tree_node *n3 = cache_alloc_node(tree); b_tree_node *n3 = cache_alloc_node(tree);
node_init(tree, n3); 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 = n3;
current_id = n3_id; current_id = n3_id;
} else { } else {
cache_free_node(tree, n3);
SWAP(b_tree_node *, current, next); SWAP(b_tree_node *, current, next);
current_id = next_id; SWAP(long, current_id, next_id);
} }
depth++; 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 current and next pointers. */
SWAP(b_tree_node *, current, next); SWAP(b_tree_node *, current, next);
current_id = next_id; SWAP(long, current_id, next_id);
nr_entries = node_get_nr_entries(tree, current); nr_entries = node_get_nr_entries(tree, current);
} }

View File

@@ -23,6 +23,7 @@ struct b_tree_ops {
const b_tree_node *); const b_tree_node *);
long (*tree_alloc_node)(struct b_tree *); 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 *); unsigned long (*node_get_nr_entries)(struct b_tree *, b_tree_node *);
void (*node_set_nr_entries)( void (*node_set_nr_entries)(
struct b_tree *, struct b_tree *,