From 3fabeeac26e405b5bd413898e5aacdabee323980 Mon Sep 17 00:00:00 2001 From: Zachary Dremann Date: Sat, 13 Jan 2024 16:49:53 -0500 Subject: [PATCH] fix(roaring64): art_find_at would return the wrong leaf If a leaf shared all but the last byte, art_find_at could return the incorrrect leaf, rather than returning NULL Fixes #552 --- src/art/art.c | 2 +- tests/roaring64_unit.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/art/art.c b/src/art/art.c index 0a220fe6b..66633a7f0 100644 --- a/src/art/art.c +++ b/src/art/art.c @@ -1093,7 +1093,7 @@ static art_val_t *art_find_at(const art_node_t *node, depth += inner_node->prefix_size + 1; } art_leaf_t *leaf = CAST_LEAF(node); - if (depth >= ART_KEY_BYTES - 1) { + if (depth >= ART_KEY_BYTES) { return (art_val_t *)leaf; } uint8_t common_prefix = diff --git a/tests/roaring64_unit.cpp b/tests/roaring64_unit.cpp index 9423ab252..89f830025 100644 --- a/tests/roaring64_unit.cpp +++ b/tests/roaring64_unit.cpp @@ -191,6 +191,7 @@ DEFINE_TEST(test_add_range_closed) { // Range spans more than two containers. roaring64_bitmap_t* r = roaring64_bitmap_create(); roaring64_bitmap_add_range_closed(r, 100, 300000); + assert_int_equal(roaring64_bitmap_get_cardinality(r), 300000 - 100 + 1); roaring64_bulk_context_t context{}; assert_false(roaring64_bitmap_contains_bulk(r, &context, 99)); for (uint64_t i = 100; i <= 300000; ++i) { @@ -199,6 +200,15 @@ DEFINE_TEST(test_add_range_closed) { assert_false(roaring64_bitmap_contains_bulk(r, &context, 300001)); roaring64_bitmap_free(r); } + { + // Add a range that spans multiple ART levels (end >> 16 == 0x0101) + roaring64_bitmap_t* r = roaring64_bitmap_create(); + uint64_t end = 0x101ffff; + uint64_t start = 0; + roaring64_bitmap_add_range_closed(r, start, end); + assert_int_equal(roaring64_bitmap_get_cardinality(r), end - start + 1); + roaring64_bitmap_free(r); + } } DEFINE_TEST(test_contains_bulk) {