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 "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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 *,
|
||||||
|
|||||||
Reference in New Issue
Block a user