Skip to content
Snippets Groups Projects
Commit 51940800 authored by Iskander Sagitov's avatar Iskander Sagitov Committed by Nikita Pettik
Browse files

lib: fix memory leak in rope_insert

Found that in case of exiting the rope_insert function with an error
some nodes are created but not deleted.

This commit fixes it and adds the test.

Test checks  that in case of this error the number of
allocated nodes and the number of freed nodes are the same.

Closes #5788
parent 911ca60e
No related branches found
No related tags found
No related merge requests found
......@@ -374,8 +374,10 @@ rope_insert(struct rope *rope, rope_size_t offset, rope_data_t data,
if (offset != 0) {
struct rope_node *split_node;
split_node = rope_node_split(rope, **p_end, offset);
if (split_node == NULL)
return -1;
if (split_node == NULL) {
ROPE_FREE(rope->ctx, new_node);
return -1;
}
split_node->link[0] = new_node;
split_node->height++;
split_node->tree_size += new_node->tree_size;
......
......@@ -33,6 +33,8 @@ add_executable(mhash_bytemap.test mhash_bytemap.c)
target_link_libraries(mhash_bytemap.test unit)
add_executable(rope_basic.test rope_basic.c)
target_link_libraries(rope_basic.test salad)
add_executable(gh-5788-rope-insert-oom.test gh-5788-rope-insert-oom.c)
target_link_libraries(gh-5788-rope-insert-oom.test salad unit)
add_executable(rope_avl.test rope_avl.c)
target_link_libraries(rope_avl.test salad)
add_executable(rope_stress.test rope_stress.c)
......
#include "unit.h"
#include <string.h>
/** Counting the number of allocated nodes */
static size_t allocated_count;
/** Counting the number of freed nodes */
static size_t freed_count;
/** Number of remaining node allocations */
static size_t remaining_allocations_count;
static inline void *
mem_alloc_sanitizer(void *data, size_t size)
{
(void) data;
if (remaining_allocations_count == 0)
return NULL;
allocated_count++;
remaining_allocations_count--;
return malloc(size);
}
static inline void
mem_free_sanitizer(void *data, void *ptr)
{
freed_count++;
(void) data;
free(ptr);
}
static inline char *
str_getn(void *ctx, char *data, size_t size, size_t offset)
{
(void) ctx;
return data + offset;
}
#define ROPE_ALLOC_F mem_alloc_sanitizer
#define ROPE_FREE_F mem_free_sanitizer
#define ROPE_SPLIT_F str_getn
#define rope_data_t char *
#define rope_ctx_t void *
#include "salad/rope.h"
static inline struct rope *
prepare_test(int max_alloc_count)
{
remaining_allocations_count = max_alloc_count;
allocated_count = 0;
freed_count = 0;
return rope_new(NULL);;
}
/**
* Test for bug fix #5788.
* Try to exit from rope_insert due to out of memory
* by limiting the available node allocations and
* check that the number of allocated
* nodes and the number of freed nodes are the same.
*/
static void
out_of_memory_stress_test()
{
header();
const int iterations = 20;
plan(iterations);
for (int max_allocs = 1; max_allocs <= iterations; ++max_allocs) {
struct rope *rope = prepare_test(max_allocs);
for(int i = 0; i <= max_allocs; ++i){
rope_insert(rope, rope_size(rope) / 2, "abcdefg", 7);
}
rope_delete(rope);
is(allocated_count, freed_count, "all allocated nodes freed");
}
check_plan();
footer();
}
int
main()
{
out_of_memory_stress_test();
return 0;
}
*** out_of_memory_stress_test ***
1..20
ok 1 - all allocated nodes freed
ok 2 - all allocated nodes freed
ok 3 - all allocated nodes freed
ok 4 - all allocated nodes freed
ok 5 - all allocated nodes freed
ok 6 - all allocated nodes freed
ok 7 - all allocated nodes freed
ok 8 - all allocated nodes freed
ok 9 - all allocated nodes freed
ok 10 - all allocated nodes freed
ok 11 - all allocated nodes freed
ok 12 - all allocated nodes freed
ok 13 - all allocated nodes freed
ok 14 - all allocated nodes freed
ok 15 - all allocated nodes freed
ok 16 - all allocated nodes freed
ok 17 - all allocated nodes freed
ok 18 - all allocated nodes freed
ok 19 - all allocated nodes freed
ok 20 - all allocated nodes freed
*** out_of_memory_stress_test: done ***
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment