From 8cf378c840f97f9aa02f194711bf7b7f224fcf2a Mon Sep 17 00:00:00 2001 From: James Zhang Date: Wed, 21 Dec 2022 15:24:26 -0800 Subject: [PATCH] Fixes memory leak in cbor_bytestring_add_chunk --- CHANGELOG.md | 1 + src/cbor/bytestrings.c | 6 ++++++ src/cbor/internal/builder_callbacks.c | 4 +++- test/memory_allocation_test.c | 3 +-- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f0db2f6..1acd6264 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Next - BUILD BREAKING: Minimum CMake version is 3.0 [[#201]](https://github.com/PJK/libcbor/pull/201) (by [thewtex@](https://github.com/thewtex)) - See https://repology.org/project/cmake/versions for support; the vast majority of users should not be affected. - Fix a potential memory leak when the allocator fails during array or map decoding [[#224]](https://github.com/PJK/libcbor/pull/224) (by [James-ZHANG](https://github.com/James-ZHANG)) +- Fix a memory leak when the allocator fails when adding chunks to indefinite strings. 0.9.0 (2021-11-14) --------------------- diff --git a/src/cbor/bytestrings.c b/src/cbor/bytestrings.c index d78d3d80..eccb539b 100644 --- a/src/cbor/bytestrings.c +++ b/src/cbor/bytestrings.c @@ -92,11 +92,15 @@ size_t cbor_bytestring_chunk_count(const cbor_item_t *item) { bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { assert(cbor_isa_bytestring(item)); assert(cbor_bytestring_is_indefinite(item)); + assert(cbor_isa_bytestring(chunk)); + assert(cbor_bytestring_is_definite(chunk)); struct cbor_indefinite_string_data *data = (struct cbor_indefinite_string_data *)item->data; if (data->chunk_count == data->chunk_capacity) { // TODO: Add a test for this if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) { + _CBOR_FREE(chunk->data); + _CBOR_FREE(chunk); return false; } @@ -108,6 +112,8 @@ bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { data->chunks, sizeof(cbor_item_t *), new_chunk_capacity); if (new_chunks_data == NULL) { + _CBOR_FREE(chunk->data); + _CBOR_FREE(chunk); return false; } data->chunk_capacity = new_chunk_capacity; diff --git a/src/cbor/internal/builder_callbacks.c b/src/cbor/internal/builder_callbacks.c index a03d971d..d218b0eb 100644 --- a/src/cbor/internal/builder_callbacks.c +++ b/src/cbor/internal/builder_callbacks.c @@ -226,7 +226,9 @@ void cbor_builder_byte_string_callback(void *context, cbor_data data, if (ctx->stack->size > 0 && cbor_isa_bytestring(ctx->stack->top->item)) { if (cbor_bytestring_is_indefinite(ctx->stack->top->item)) { - cbor_bytestring_add_chunk(ctx->stack->top->item, cbor_move(res)); + if (!cbor_bytestring_add_chunk(ctx->stack->top->item, cbor_move(res))) { + ctx->creation_failed = true; + } } else { cbor_decref(&res); ctx->syntax_error = true; diff --git a/test/memory_allocation_test.c b/test/memory_allocation_test.c index ff58c27f..9ce89046 100644 --- a/test/memory_allocation_test.c +++ b/test/memory_allocation_test.c @@ -187,14 +187,13 @@ static void test_bytestring_add_chunk(void **_CBOR_UNUSED(_state)) { cbor_item_t *bytestring = cbor_new_indefinite_bytestring(); cbor_item_t *chunk = cbor_build_bytestring(bytes, 4); - assert_false(cbor_bytestring_add_chunk(bytestring, chunk)); + assert_false(cbor_bytestring_add_chunk(bytestring, cbor_move(chunk))); assert_int_equal(cbor_bytestring_chunk_count(bytestring), 0); assert_int_equal( ((struct cbor_indefinite_string_data *)bytestring->data) ->chunk_capacity, 0); - cbor_decref(&chunk); cbor_decref(&bytestring); }, 5, MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);