Skip to content

Commit ceebb78

Browse files
committed
all: handle properly OOM on *_create()
Fix dereferencing of malloc() on OOM conditions (NULL dereferrencing) Added OOM test and CHANGELOG entries. Reported-by: CodexGPT-5.3 <noreply@openai.com>
1 parent 2ebb88e commit ceebb78

9 files changed

Lines changed: 129 additions & 0 deletions

File tree

.github/workflows/test_script.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ echo "Building out-tree"
2020
cd build
2121
../configure $CONFIG_FLAGS || (cat config.log && /bin/false)
2222
make check || ((for f in `find test/ -name "*.log"`; do cat $f; done;) && /bin/false)
23+
echo "Running oom_create_test without valgrind..."
24+
./test/oom_create_test
2325
2426
echo "Running examples..."
2527
valgrind --leak-check=full examples/bbitmap

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ Legend:
1313

1414
- [B] utils: fix `cdada_strerr()` bounds handling for invalid and negative error codes
1515
- [B] utils: add missing human-readable message for `CDADA_E_FULL`
16+
- [B] list/map/queue/set/stack: return `NULL` when constructor `malloc()` fails (avoid null dereference)
1617
- [O] tests: add coverage for `cdada_strerr()` valid, boundary and high invalid values
18+
- [O] tests: add `oom_create_test` coverage for create paths (`list`, `map`, `queue`, `set`, `stack`, `str`, `bbitmap`)
1719

1820
### v0.6.3 (28th January 2026)
1921

src/list.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ cdada_list_t* __cdada_list_create(const uint16_t val_size,
1616
return m;
1717

1818
m = (__cdada_list_int_t*)malloc(sizeof(__cdada_list_int_t));
19+
if(!m)
20+
return NULL;
1921
memset(m, 0, sizeof(__cdada_list_int_t));
2022
m->magic_num = CDADA_MAGIC;
2123
m->user_val_len = val_size;

src/map.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ cdada_map_t* __cdada_map_create(const uint16_t key_size,
1616
return m;
1717

1818
m = (__cdada_map_int_t*)malloc(sizeof(__cdada_map_int_t));
19+
if(!m)
20+
return NULL;
1921
memset(m, 0, sizeof(__cdada_map_int_t));
2022
m->magic_num = CDADA_MAGIC;
2123
m->user_key_len = key_size;

src/queue.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ cdada_queue_t* __cdada_queue_create(const uint16_t val_size,
1616
return m;
1717

1818
m = (__cdada_queue_int_t*)malloc(sizeof(__cdada_queue_int_t));
19+
if(!m)
20+
return NULL;
1921
memset(m, 0, sizeof(__cdada_queue_int_t));
2022
m->magic_num = CDADA_MAGIC;
2123
m->user_val_len = val_size;

src/set.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ cdada_set_t* __cdada_set_create(const uint16_t key_size,
1616
return m;
1717

1818
m = (__cdada_set_int_t*)malloc(sizeof(__cdada_set_int_t));
19+
if(!m)
20+
return NULL;
1921
memset(m, 0, sizeof(__cdada_set_int_t));
2022
m->magic_num = CDADA_MAGIC;
2123
m->user_key_len = key_size;

src/stack.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ cdada_stack_t* __cdada_stack_create(const uint16_t val_size,
1616
return m;
1717

1818
m = (__cdada_stack_int_t*)malloc(sizeof(__cdada_stack_int_t));
19+
if(!m)
20+
return NULL;
1921
memset(m, 0, sizeof(__cdada_stack_int_t));
2022
m->magic_num = CDADA_MAGIC;
2123
m->user_val_len = val_size;

test/Makefile.am

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ check_PROGRAMS= bbitmap_test \
88
cdada_include_test \
99
list_test \
1010
map_test \
11+
oom_create_test \
1112
queue_test \
1213
set_test \
1314
stack_test \
@@ -40,6 +41,10 @@ map_test_SOURCES= map_test.c map_custom.cc
4041
map_test_CPPFLAGS= -I$(top_builddir)/include/ -I$(top_srcdir)/include/
4142
map_test_LDADD= -lpthread ../src/libcdada.la
4243

44+
oom_create_test_SOURCES= oom_create_test.c
45+
oom_create_test_CPPFLAGS= -I$(top_builddir)/include/ -I$(top_srcdir)/include/
46+
oom_create_test_LDADD= -lpthread ../src/libcdada.la
47+
4348
queue_test_SOURCES= queue_test.c queue_custom.cc
4449
queue_test_CPPFLAGS= -I$(top_builddir)/include/ -I$(top_srcdir)/include/
4550
queue_test_LDADD= -lpthread ../src/libcdada.la
@@ -71,6 +76,8 @@ TESTS_ENVIRONMENT=valgrind --trace-children=yes --error-exitcode=1 \
7176
--dsymutil=yes --leak-check=yes \
7277
--leak-check-heuristics=all \
7378
--suppressions=$(top_srcdir)/test/locale.supp
79+
else
80+
TESTS += oom_create_test
7481
endif
7582

7683
if HAVE_PYTHON

test/oom_create_test.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
4+
#include "cdada/bbitmap.h"
5+
#include "cdada/list.h"
6+
#include "cdada/map.h"
7+
#include "cdada/queue.h"
8+
#include "cdada/set.h"
9+
#include "cdada/stack.h"
10+
#include "cdada/str.h"
11+
#include "common.h"
12+
13+
static int g_fail_next_malloc = 0;
14+
15+
#ifdef __GLIBC__
16+
extern void* __libc_malloc(size_t size);
17+
18+
void* malloc(size_t size){
19+
if(g_fail_next_malloc)
20+
return NULL;
21+
return __libc_malloc(size);
22+
}
23+
#endif
24+
25+
int main(int argc, char** argv){
26+
cdada_list_t* list;
27+
cdada_map_t* map;
28+
cdada_queue_t* queue;
29+
cdada_set_t* set;
30+
cdada_stack_t* stack;
31+
cdada_str_t* str;
32+
cdada_bbitmap_t* bbitmap;
33+
34+
(void)argc;
35+
(void)argv;
36+
37+
g_fail_next_malloc = 0;
38+
list = cdada_list_create(uint32_t);
39+
TEST_ASSERT(list != NULL);
40+
TEST_ASSERT(cdada_list_destroy(list) == CDADA_SUCCESS);
41+
42+
g_fail_next_malloc = 1;
43+
list = cdada_list_create(uint32_t);
44+
g_fail_next_malloc = 0;
45+
TEST_ASSERT(list == NULL);
46+
47+
g_fail_next_malloc = 0;
48+
map = cdada_map_create(uint32_t);
49+
TEST_ASSERT(map != NULL);
50+
TEST_ASSERT(cdada_map_destroy(map) == CDADA_SUCCESS);
51+
52+
g_fail_next_malloc = 1;
53+
map = cdada_map_create(uint32_t);
54+
g_fail_next_malloc = 0;
55+
TEST_ASSERT(map == NULL);
56+
57+
g_fail_next_malloc = 0;
58+
queue = cdada_queue_create(uint32_t);
59+
TEST_ASSERT(queue != NULL);
60+
TEST_ASSERT(cdada_queue_destroy(queue) == CDADA_SUCCESS);
61+
62+
g_fail_next_malloc = 1;
63+
queue = cdada_queue_create(uint32_t);
64+
g_fail_next_malloc = 0;
65+
TEST_ASSERT(queue == NULL);
66+
67+
g_fail_next_malloc = 0;
68+
set = cdada_set_create(uint32_t);
69+
TEST_ASSERT(set != NULL);
70+
TEST_ASSERT(cdada_set_destroy(set) == CDADA_SUCCESS);
71+
72+
g_fail_next_malloc = 1;
73+
set = cdada_set_create(uint32_t);
74+
g_fail_next_malloc = 0;
75+
TEST_ASSERT(set == NULL);
76+
77+
g_fail_next_malloc = 0;
78+
stack = cdada_stack_create(uint32_t);
79+
TEST_ASSERT(stack != NULL);
80+
TEST_ASSERT(cdada_stack_destroy(stack) == CDADA_SUCCESS);
81+
82+
g_fail_next_malloc = 1;
83+
stack = cdada_stack_create(uint32_t);
84+
g_fail_next_malloc = 0;
85+
TEST_ASSERT(stack == NULL);
86+
87+
g_fail_next_malloc = 0;
88+
str = cdada_str_create("oom");
89+
TEST_ASSERT(str != NULL);
90+
TEST_ASSERT(cdada_str_destroy(str) == CDADA_SUCCESS);
91+
92+
g_fail_next_malloc = 1;
93+
str = cdada_str_create("oom");
94+
g_fail_next_malloc = 0;
95+
TEST_ASSERT(str == NULL);
96+
97+
g_fail_next_malloc = 0;
98+
bbitmap = cdada_bbitmap_create(64);
99+
TEST_ASSERT(bbitmap != NULL);
100+
TEST_ASSERT(cdada_bbitmap_destroy(bbitmap) == CDADA_SUCCESS);
101+
102+
g_fail_next_malloc = 1;
103+
bbitmap = cdada_bbitmap_create(64);
104+
g_fail_next_malloc = 0;
105+
TEST_ASSERT(bbitmap == NULL);
106+
107+
return EXIT_SUCCESS;
108+
}

0 commit comments

Comments
 (0)