b-tree: fix incorrect copy bounds and pointer swaps
This commit is contained in:
64
src/b-tree.c
64
src/b-tree.c
@@ -1,5 +1,7 @@
|
||||
#include "b-tree.h"
|
||||
|
||||
#include "bin.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <blue/core/queue.h>
|
||||
#include <stdlib.h>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 *,
|
||||
|
||||
Reference in New Issue
Block a user