From 835290dfdf27ab89692b4bb84b9e7c43ff04e5a9 Mon Sep 17 00:00:00 2001 From: Andreas Pasiopoulos Date: Thu, 11 Aug 2016 17:18:46 +0300 Subject: [PATCH 1/3] Add a test case for OOM while allocating memory --- test/suites/api/test_memory_funcs.c | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/test/suites/api/test_memory_funcs.c b/test/suites/api/test_memory_funcs.c index 047ca67..ac58809 100644 --- a/test/suites/api/test_memory_funcs.c +++ b/test/suites/api/test_memory_funcs.c @@ -5,8 +5,9 @@ static int malloc_called = 0; static int free_called = 0; +static size_t malloc_used = 0; -/* helper */ +/* helpers */ static void create_and_free_complex_object() { json_t *obj; @@ -22,6 +23,20 @@ static void create_and_free_complex_object() json_decref(obj); } +static void create_and_free_object_with_oom() +{ + json_t *obj = json_object(); + + for (int i = 0; i < 10; i++) + { + char key[4]; + snprintf(key, sizeof key, "%d", i); + json_object_set_new(obj, key, json_integer(i)); + } + + json_decref(obj); +} + static void *my_malloc(size_t size) { malloc_called = 1; @@ -49,6 +64,32 @@ static void test_simple() } +static void *oom_malloc(size_t size) +{ + if (malloc_used + size > 800) + return NULL; + + malloc_used += size; + return malloc(size); +} + +static void oom_free(void *ptr) +{ + free_called++; + free(ptr); +} + +static void test_oom() +{ + free_called = 0; + json_set_alloc_funcs(oom_malloc, oom_free); + create_and_free_object_with_oom(); + + if (free_called == 0) + fail("Allocation with OOM failed"); +} + + /* Test the secure memory functions code given in the API reference documentation, but by using plain memset instead of @@ -84,4 +125,5 @@ static void run_tests() { test_simple(); test_secure_funcs(); + test_oom(); } From 86fdf76f7942d6a3921f66d792efb0e866f609bd Mon Sep 17 00:00:00 2001 From: Andreas Pasiopoulos Date: Thu, 11 Aug 2016 17:48:29 +0300 Subject: [PATCH 2/3] Check the allocation was successful before freeing existing hashtable buckets and increasing hashtable order Fixes a crash observed when there is OOM in hashtable_do_rehash --- src/hashtable.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/hashtable.c b/src/hashtable.c index a453b00..76214f0 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -152,16 +152,18 @@ static int hashtable_do_rehash(hashtable_t *hashtable) { list_t *list, *next; pair_t *pair; - size_t i, index, new_size; + size_t i, index, new_size, new_order; + + new_order = hashtable->order + 1; + new_size = hashsize(new_order); + + struct hashtable_bucket *new_buckets = jsonp_malloc(new_size * sizeof(bucket_t)); + if(!new_buckets) + return -1; jsonp_free(hashtable->buckets); - - hashtable->order++; - new_size = hashsize(hashtable->order); - - hashtable->buckets = jsonp_malloc(new_size * sizeof(bucket_t)); - if(!hashtable->buckets) - return -1; + hashtable->buckets = new_buckets; + hashtable->order = new_order; for(i = 0; i < hashsize(hashtable->order); i++) { From 6a4b3f878dddb1525b59b86da7fb392ab8fdc7b2 Mon Sep 17 00:00:00 2001 From: Andreas Pasiopoulos Date: Thu, 11 Aug 2016 18:51:29 +0300 Subject: [PATCH 3/3] Conform to c89 --- src/hashtable.c | 3 ++- test/suites/api/test_memory_funcs.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hashtable.c b/src/hashtable.c index 76214f0..0ec1ef8 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -153,11 +153,12 @@ static int hashtable_do_rehash(hashtable_t *hashtable) list_t *list, *next; pair_t *pair; size_t i, index, new_size, new_order; + struct hashtable_bucket *new_buckets; new_order = hashtable->order + 1; new_size = hashsize(new_order); - struct hashtable_bucket *new_buckets = jsonp_malloc(new_size * sizeof(bucket_t)); + new_buckets = jsonp_malloc(new_size * sizeof(bucket_t)); if(!new_buckets) return -1; diff --git a/test/suites/api/test_memory_funcs.c b/test/suites/api/test_memory_funcs.c index ac58809..7cb4b73 100644 --- a/test/suites/api/test_memory_funcs.c +++ b/test/suites/api/test_memory_funcs.c @@ -25,11 +25,12 @@ static void create_and_free_complex_object() static void create_and_free_object_with_oom() { + int i; + char key[4]; json_t *obj = json_object(); - for (int i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { - char key[4]; snprintf(key, sizeof key, "%d", i); json_object_set_new(obj, key, json_integer(i)); }