Repository: RoaringBitmap/CRoaring (C)

Issue:
Leak in roaring_bitmap_or_many_heap
Found via fuzzing for croaring-rs, still could probably be minified some, but not easily done so far. Using amalgamation generated from current master.

```c
#include "roaring.h"

int main() {
  roaring_bitmap_t *b1 = roaring_bitmap_create();
  roaring_bitmap_t *b2 = roaring_bitmap_create();

  roaring_bitmap_flip_inplace(b2, 217939, 241583 + 1);
  roaring_bitmap_add(b2, 261888);
  roaring_bitmap_remove_range(b2, 65455, 241583 + 1);

  roaring_bitmap_or_inplace(b1, b2);

  const roaring_bitmap_t *bitmaps[] = {b1, b2};
  roaring_bitmap_t *result = roaring_bitmap_or_many_heap(2, bitmaps);

  roaring_bitmap_free(result);
  roaring_bitmap_free(b1);
  roaring_bitmap_free(b2);
  return 0;
}
```

Output under valgrind:

```
==235387== Memcheck, a memory error detector
==235387== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==235387== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==235387== Command: ./main
==235387==
==235387==
==235387== HEAP SUMMARY:
==235387==     in use at exit: 24 bytes in 2 blocks
==235387==   total heap usage: 16 allocs, 14 frees, 333 bytes allocated
==235387==
==235387== 24 (16 direct, 8 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==235387==    at 0x4865250: malloc (vg_replace_malloc.c:393)
==235387==    by 0x124907: roaring_malloc (roaring.c:15152)
==235387==    by 0x121A97: run_container_create_given_capacity (roaring.c:14273)
==235387==    by 0x121BDB: run_container_create (roaring.c:14298)
==235387==    by 0x10E1EB: container_lazy_or (roaring.c:5422)
==235387==    by 0x12BD0B: roaring_bitmap_lazy_or (roaring.c:17510)
==235387==    by 0x132B1B: roaring_bitmap_or_many_heap (roaring.c:19625)
==235387==    by 0x108E4B: main (main.c:14)
==235387==
==235387== LEAK SUMMARY:
==235387==    definitely lost: 16 bytes in 1 blocks
==235387==    indirectly lost: 8 bytes in 1 blocks
==235387==      possibly lost: 0 bytes in 0 blocks
==235387==    still reachable: 0 bytes in 0 blocks
==235387==         suppressed: 0 bytes in 0 blocks
==235387==
==235387== For lists of detected and suppressed errors, rerun with: -s
==235387== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
```


Discussion: Slightly minimized:

```c
#include "roaring.h"

int main() {
  roaring_bitmap_t *b1 = roaring_bitmap_create();

  roaring_bitmap_add_range(b1, 0, 100);
  roaring_bitmap_remove_range(b1, 0, 99);

  roaring_bitmap_t *b2 = roaring_bitmap_copy(b1);

  const roaring_bitmap_t *bitmaps[] = {b1, b2};
  roaring_bitmap_t *result = roaring_bitmap_or_many_heap(2, bitmaps);

  roaring_bitmap_free(result);
  roaring_bitmap_free(b2);
  roaring_bitmap_free(b1);
  return 0;
}
```

It appears to depend on a range container representing a single number: changing the `99` to `98` (changing to a single range, but covering two numbers) causes the memory leak to go away.

Adding a `roaring_bitmap_add(b1, 110)` (changing to two ranges, both with one number each) still shows the memory leak.
Verified. This is real.



Fix (patch):
diff --git a/include/roaring/containers/containers.h b/include/roaring/containers/containers.h
index ad78515d1..782bf1370 100644
--- a/include/roaring/containers/containers.h
+++ b/include/roaring/containers/containers.h
@@ -1179,7 +1179,7 @@ static inline container_t *container_lazy_or(
                                 CAST_run(result));
             *result_type = RUN_CONTAINER_TYPE;
             // we are being lazy
-            result = convert_run_to_efficient_container(
+            result = convert_run_to_efficient_container_and_free(
                 CAST_run(result), result_type);
             return result;