Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add null checks to roaring64 #633

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions src/roaring64.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,19 @@ static inline uint64_t minimum(uint64_t a, uint64_t b) {

static inline leaf_t *create_leaf(container_t *container, uint8_t typecode) {
leaf_t *leaf = (leaf_t *)roaring_malloc(sizeof(leaf_t));
if (leaf == NULL) {
return NULL;
}
leaf->container = container;
leaf->typecode = typecode;
return leaf;
}

static inline leaf_t *copy_leaf_container(const leaf_t *leaf) {
leaf_t *result_leaf = (leaf_t *)roaring_malloc(sizeof(leaf_t));
if (result_leaf == NULL) {
return NULL;
}
result_leaf->typecode = leaf->typecode;
// get_copy_of_container modifies the typecode passed in.
result_leaf->container = get_copy_of_container(
Expand Down Expand Up @@ -142,6 +148,9 @@ static inline roaring64_iterator_t *roaring64_iterator_init_at(
roaring64_bitmap_t *roaring64_bitmap_create(void) {
roaring64_bitmap_t *r =
(roaring64_bitmap_t *)roaring_malloc(sizeof(roaring64_bitmap_t));
if (r == NULL) {
return NULL;
}
r->art.root = NULL;
r->flags = 0;
return r;
Expand All @@ -164,13 +173,20 @@ void roaring64_bitmap_free(roaring64_bitmap_t *r) {

roaring64_bitmap_t *roaring64_bitmap_copy(const roaring64_bitmap_t *r) {
roaring64_bitmap_t *result = roaring64_bitmap_create();
if (result == NULL) {
return NULL;
}

art_iterator_t it = art_init_iterator(&r->art, /*first=*/true);
while (it.value != NULL) {
leaf_t *leaf = (leaf_t *)it.value;
uint8_t result_typecode = leaf->typecode;
container_t *result_container = get_copy_of_container(
leaf->container, &result_typecode, /*copy_on_write=*/false);
if (result_container == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
leaf_t *result_leaf = create_leaf(result_container, result_typecode);
art_insert(&result->art, it.key, (art_val_t *)result_leaf);
art_iterator_next(&it);
Expand All @@ -184,6 +200,9 @@ roaring64_bitmap_t *roaring64_bitmap_from_range(uint64_t min, uint64_t max,
return NULL;
}
roaring64_bitmap_t *r = roaring64_bitmap_create();
if (r == NULL) {
return NULL;
}
if (step >= (1 << 16)) {
// Only one value per container.
for (uint64_t value = min; value < max; value += step) {
Expand Down Expand Up @@ -221,12 +240,18 @@ roaring64_bitmap_t *roaring64_bitmap_from_range(uint64_t min, uint64_t max,
roaring64_bitmap_t *roaring64_bitmap_of_ptr(size_t n_args,
const uint64_t *vals) {
roaring64_bitmap_t *r = roaring64_bitmap_create();
if (r == NULL) {
return NULL;
}
roaring64_bitmap_add_many(r, n_args, vals);
return r;
}

roaring64_bitmap_t *roaring64_bitmap_of(size_t n_args, ...) {
roaring64_bitmap_t *r = roaring64_bitmap_create();
if (r == NULL) {
return NULL;
}
roaring64_bulk_context_t context = {0, 0, 0, 0, 0, 0, 0};
va_list ap;
va_start(ap, n_args);
Expand Down Expand Up @@ -939,6 +964,9 @@ bool roaring64_bitmap_is_strict_subset(const roaring64_bitmap_t *r1,
roaring64_bitmap_t *roaring64_bitmap_and(const roaring64_bitmap_t *r1,
const roaring64_bitmap_t *r2) {
roaring64_bitmap_t *result = roaring64_bitmap_create();
if (result == NULL) {
return NULL;
}

art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
art_iterator_t it2 = art_init_iterator(&r2->art, /*first=*/true);
Expand All @@ -952,6 +980,10 @@ roaring64_bitmap_t *roaring64_bitmap_and(const roaring64_bitmap_t *r1,
if (compare_result == 0) {
// Case 2: iterators at the same high key position.
leaf_t *result_leaf = (leaf_t *)roaring_malloc(sizeof(leaf_t));
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
leaf_t *leaf1 = (leaf_t *)it1.value;
leaf_t *leaf2 = (leaf_t *)it2.value;
result_leaf->container = container_and(
Expand Down Expand Up @@ -1141,6 +1173,9 @@ double roaring64_bitmap_jaccard_index(const roaring64_bitmap_t *r1,
roaring64_bitmap_t *roaring64_bitmap_or(const roaring64_bitmap_t *r1,
const roaring64_bitmap_t *r2) {
roaring64_bitmap_t *result = roaring64_bitmap_create();
if (result == NULL) {
return NULL;
}

art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
art_iterator_t it2 = art_init_iterator(&r2->art, /*first=*/true);
Expand All @@ -1164,6 +1199,10 @@ roaring64_bitmap_t *roaring64_bitmap_or(const roaring64_bitmap_t *r1,
leaf_t *leaf1 = (leaf_t *)it1.value;
leaf_t *leaf2 = (leaf_t *)it2.value;
leaf_t *result_leaf = (leaf_t *)roaring_malloc(sizeof(leaf_t));
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
result_leaf->container = container_or(
leaf1->container, leaf1->typecode, leaf2->container,
leaf2->typecode, &result_leaf->typecode);
Expand All @@ -1175,11 +1214,19 @@ roaring64_bitmap_t *roaring64_bitmap_or(const roaring64_bitmap_t *r1,
if ((it1_present && !it2_present) || compare_result < 0) {
// Cases 1 and 3a: it1 is the only iterator or is before it2.
leaf_t *result_leaf = copy_leaf_container((leaf_t *)it1.value);
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
art_insert(&result->art, it1.key, (art_val_t *)result_leaf);
art_iterator_next(&it1);
} else if ((!it1_present && it2_present) || compare_result > 0) {
// Cases 2 and 3c: it2 is the only iterator or is before it1.
leaf_t *result_leaf = copy_leaf_container((leaf_t *)it2.value);
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
art_insert(&result->art, it2.key, (art_val_t *)result_leaf);
art_iterator_next(&it2);
}
Expand Down Expand Up @@ -1247,6 +1294,9 @@ void roaring64_bitmap_or_inplace(roaring64_bitmap_t *r1,
} else if ((!it1_present && it2_present) || compare_result > 0) {
// Cases 2 and 3c: it2 is the only iterator or is before it1.
leaf_t *result_leaf = copy_leaf_container((leaf_t *)it2.value);
if (result_leaf == NULL) {
return;
}
art_iterator_insert(&r1->art, &it1, it2.key,
(art_val_t *)result_leaf);
art_iterator_next(&it2);
Expand All @@ -1257,6 +1307,9 @@ void roaring64_bitmap_or_inplace(roaring64_bitmap_t *r1,
roaring64_bitmap_t *roaring64_bitmap_xor(const roaring64_bitmap_t *r1,
const roaring64_bitmap_t *r2) {
roaring64_bitmap_t *result = roaring64_bitmap_create();
if (result == NULL) {
return NULL;
}

art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
art_iterator_t it2 = art_init_iterator(&r2->art, /*first=*/true);
Expand All @@ -1280,6 +1333,10 @@ roaring64_bitmap_t *roaring64_bitmap_xor(const roaring64_bitmap_t *r1,
leaf_t *leaf1 = (leaf_t *)it1.value;
leaf_t *leaf2 = (leaf_t *)it2.value;
leaf_t *result_leaf = (leaf_t *)roaring_malloc(sizeof(leaf_t));
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
result_leaf->container = container_xor(
leaf1->container, leaf1->typecode, leaf2->container,
leaf2->typecode, &result_leaf->typecode);
Expand All @@ -1298,11 +1355,19 @@ roaring64_bitmap_t *roaring64_bitmap_xor(const roaring64_bitmap_t *r1,
if ((it1_present && !it2_present) || compare_result < 0) {
// Cases 1 and 3a: it1 is the only iterator or is before it2.
leaf_t *result_leaf = copy_leaf_container((leaf_t *)it1.value);
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
art_insert(&result->art, it1.key, (art_val_t *)result_leaf);
art_iterator_next(&it1);
} else if ((!it1_present && it2_present) || compare_result > 0) {
// Cases 2 and 3c: it2 is the only iterator or is before it1.
leaf_t *result_leaf = copy_leaf_container((leaf_t *)it2.value);
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
art_insert(&result->art, it2.key, (art_val_t *)result_leaf);
art_iterator_next(&it2);
}
Expand Down Expand Up @@ -1382,6 +1447,9 @@ void roaring64_bitmap_xor_inplace(roaring64_bitmap_t *r1,
} else if ((!it1_present && it2_present) || compare_result > 0) {
// Cases 2 and 3c: it2 is the only iterator or is before it1.
leaf_t *result_leaf = copy_leaf_container((leaf_t *)it2.value);
if (result_leaf == NULL) {
return;
}
if (it1_present) {
art_iterator_insert(&r1->art, &it1, it2.key,
(art_val_t *)result_leaf);
Expand All @@ -1397,6 +1465,9 @@ void roaring64_bitmap_xor_inplace(roaring64_bitmap_t *r1,
roaring64_bitmap_t *roaring64_bitmap_andnot(const roaring64_bitmap_t *r1,
const roaring64_bitmap_t *r2) {
roaring64_bitmap_t *result = roaring64_bitmap_create();
if (result == NULL) {
return NULL;
}

art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
art_iterator_t it2 = art_init_iterator(&r2->art, /*first=*/true);
Expand All @@ -1415,6 +1486,10 @@ roaring64_bitmap_t *roaring64_bitmap_andnot(const roaring64_bitmap_t *r1,
if (compare_result == 0) {
// Case 2b: iterators at the same high key position.
leaf_t *result_leaf = (leaf_t *)roaring_malloc(sizeof(leaf_t));
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
leaf_t *leaf1 = (leaf_t *)it1.value;
leaf_t *leaf2 = (leaf_t *)it2.value;
result_leaf->container = container_andnot(
Expand All @@ -1436,6 +1511,10 @@ roaring64_bitmap_t *roaring64_bitmap_andnot(const roaring64_bitmap_t *r1,
if (!it2_present || compare_result < 0) {
// Cases 1 and 2a: it1 is the only iterator or is before it2.
leaf_t *result_leaf = copy_leaf_container((leaf_t *)it1.value);
if (result_leaf == NULL) {
roaring64_bitmap_free(result);
return NULL;
}
art_insert(&result->art, it1.key, (art_val_t *)result_leaf);
art_iterator_next(&it1);
} else if (compare_result > 0) {
Expand Down Expand Up @@ -1608,6 +1687,9 @@ roaring64_bitmap_t *roaring64_bitmap_flip_closed(const roaring64_bitmap_t *r1,
uint64_t max_high48_bits = (max & 0xFFFFFFFFFFFF0000ULL) >> 16;

roaring64_bitmap_t *r2 = roaring64_bitmap_create();
if (r2 == NULL) {
return NULL;
}
art_iterator_t it = art_init_iterator(&r1->art, /*first=*/true);

// Copy the containers before min unchanged.
Expand All @@ -1616,6 +1698,10 @@ roaring64_bitmap_t *roaring64_bitmap_flip_closed(const roaring64_bitmap_t *r1,
uint8_t typecode2 = leaf1->typecode;
container_t *container2 = get_copy_of_container(
leaf1->container, &typecode2, /*copy_on_write=*/false);
if (container2 == NULL) {
roaring64_bitmap_free(r2);
return NULL;
}
art_insert(&r2->art, it.key,
(art_val_t *)create_leaf(container2, typecode2));
art_iterator_next(&it);
Expand Down Expand Up @@ -1650,6 +1736,10 @@ roaring64_bitmap_t *roaring64_bitmap_flip_closed(const roaring64_bitmap_t *r1,
uint8_t typecode2 = leaf1->typecode;
container_t *container2 = get_copy_of_container(
leaf1->container, &typecode2, /*copy_on_write=*/false);
if (container2 == NULL) {
roaring64_bitmap_free(r2);
return NULL;
}
art_insert(&r2->art, it.key,
(art_val_t *)create_leaf(container2, typecode2));
art_iterator_next(&it);
Expand Down Expand Up @@ -1916,6 +2006,9 @@ roaring64_bitmap_t *roaring64_bitmap_portable_deserialize_safe(
}

roaring64_bitmap_t *r = roaring64_bitmap_create();
if (r == NULL) {
return NULL;
}
// Iterate through buckets ordered by increasing keys.
for (uint64_t bucket = 0; bucket < buckets; ++bucket) {
// Read as uint32 the most significant 32 bits of the bucket.
Expand Down Expand Up @@ -1994,13 +2087,19 @@ void roaring64_bitmap_to_uint64_array(const roaring64_bitmap_t *r,
roaring64_iterator_t *roaring64_iterator_create(const roaring64_bitmap_t *r) {
roaring64_iterator_t *it =
(roaring64_iterator_t *)roaring_malloc(sizeof(roaring64_iterator_t));
if (it == NULL) {
return NULL;
}
return roaring64_iterator_init_at(r, it, /*first=*/true);
}

roaring64_iterator_t *roaring64_iterator_create_last(
const roaring64_bitmap_t *r) {
roaring64_iterator_t *it =
(roaring64_iterator_t *)roaring_malloc(sizeof(roaring64_iterator_t));
if (it == NULL) {
return NULL;
}
return roaring64_iterator_init_at(r, it, /*first=*/false);
}

Expand All @@ -2017,6 +2116,9 @@ void roaring64_iterator_reinit_last(const roaring64_bitmap_t *r,
roaring64_iterator_t *roaring64_iterator_copy(const roaring64_iterator_t *it) {
roaring64_iterator_t *new_it =
(roaring64_iterator_t *)roaring_malloc(sizeof(roaring64_iterator_t));
if (new_it == NULL) {
return NULL;
}
memcpy(new_it, it, sizeof(*it));
return new_it;
}
Expand Down
Loading