From ba1d7f8d1cb2bd54bd983dc5393f010e5772b9ad Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Tue, 31 Jan 2023 09:41:56 +0100 Subject: [PATCH] heap: Fix erroneous value returned by heap_caps_get_allocated_size() when poisoning is enabled When light (or comprehensive) poisoning is enabled, the size requested by the user for allocation is extended by a few bytes to store the canary header and footer. heap_caps_get_allocated_size() should return the original size asked by the user (without the additional canary bytes). test_malloc.c extended with a new test assuring that heap_caps_get_allocated_size() returns the proper size regardless of the degree of poisoning. --- components/heap/multi_heap_poisoning.c | 1 + components/heap/test_apps/main/test_malloc.c | 25 ++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/components/heap/multi_heap_poisoning.c b/components/heap/multi_heap_poisoning.c index 1e3afcf0fb..44fcbe68c5 100644 --- a/components/heap/multi_heap_poisoning.c +++ b/components/heap/multi_heap_poisoning.c @@ -383,6 +383,7 @@ size_t multi_heap_get_allocated_size(multi_heap_handle_t heap, void *p) poison_head_t *head = verify_allocated_region(p, true); assert(head != NULL); size_t result = multi_heap_get_allocated_size_impl(heap, head); + subtract_poison_overhead(&result); return result; } diff --git a/components/heap/test_apps/main/test_malloc.c b/components/heap/test_apps/main/test_malloc.c index 0fe523a7a0..33c2480b2d 100644 --- a/components/heap/test_apps/main/test_malloc.c +++ b/components/heap/test_apps/main/test_malloc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -23,7 +23,6 @@ static int **allocatedMem; static int noAllocated; - static int tryAllocMem(void) { int i, j; const int allocateMaxK=1024*5; //try to allocate a max of 5MiB @@ -159,3 +158,25 @@ TEST_CASE("malloc/calloc(0) should not call failure callback", "[heap]") TEST_ASSERT_NULL(ptr); TEST_ASSERT_FALSE(failure_occured); } + +TEST_CASE("test get allocated size", "[heap]") +{ + const size_t iterations = 32; + + for (size_t i = 0; i < iterations; i++) { + // minimum block size is 12, so to avoid unecessary logic in the test, + // set the minimum requested size to 12. + const size_t alloc_size = rand() % 1024 + 12; + + void *ptr = heap_caps_malloc(alloc_size, MALLOC_CAP_DEFAULT); + TEST_ASSERT_NOT_NULL(ptr); + + // test that the heap_caps_get_allocated_size() returns the right number of bytes (aligned to 4 bytes + // since the heap component aligns to 4 bytes) + const size_t aligned_size = (alloc_size + 3) & ~3; + printf("initial size: %d, requested size : %d, allocated size: %d\n", alloc_size, aligned_size, heap_caps_get_allocated_size(ptr)); + TEST_ASSERT_EQUAL(aligned_size, heap_caps_get_allocated_size(ptr)); + + heap_caps_free(ptr); + } +}