From 9393b12cac9e58f724de63256d56ded7a6e785b1 Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Tue, 9 Aug 2022 13:10:44 +0200 Subject: [PATCH 1/2] Add a function hook called in tlsf_check() on every free block of memory In this commit: - We add a weak delcaration of tlsf_check_hook() in tlsf.h. - We call tlsf_check_hook() in tlsf_check() if the function has a defintion This hook function allows the user to implement application specific checks on the memory of every free blocks (e.g. check for memory corruption). --- tlsf.c | 21 ++++++++++++++++++++- tlsf.h | 2 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tlsf.c b/tlsf.c index 189df06..092553b 100644 --- a/tlsf.c +++ b/tlsf.c @@ -673,7 +673,8 @@ int tlsf_check(tlsf_t tlsf) while (block != &control->block_null) { int fli, sli; - tlsf_insist(block_is_free(block) && "block should be free"); + const bool is_block_free = block_is_free(block); + tlsf_insist(is_block_free && "block should be free"); tlsf_insist(!block_is_prev_free(block) && "blocks should have coalesced"); tlsf_insist(!block_is_free(block_next(block)) && "blocks should have coalesced"); tlsf_insist(block_is_prev_free(block_next(block)) && "block should be free"); @@ -681,6 +682,24 @@ int tlsf_check(tlsf_t tlsf) mapping_insert(block_size(block), &fli, &sli); tlsf_insist(fli == i && sli == j && "block size indexed in wrong list"); + + if (tlsf_check_hook != NULL) + { + /* block_size(block) returns the size of the usable memory when the block is allocated. + * As the block under test is free, we need to subtract to the block size the next_free + * and prev_free fields of the block header as they are not a part of the usable memory + * when the block is free. In addition, we also need to subtract the size of prev_phys_block + * as this field is in fact part of the current free block and not part of the next (allocated) + * block. Check the comments in block_split function for more details. + */ + const size_t actual_free_block_size = block_size(block) + - offsetof(block_header_t, next_free) + - block_header_overhead; + + tlsf_insist(tlsf_check_hook((void*)block + sizeof(block_header_t), + actual_free_block_size, is_block_free)); + } + block = block->next_free; } } diff --git a/tlsf.h b/tlsf.h index 2d6cc51..a36017f 100644 --- a/tlsf.h +++ b/tlsf.h @@ -64,6 +64,8 @@ int tlsf_check_pool(pool_t pool); */ __attribute__((weak)) void block_absorb_post_hook(void *start, size_t size, bool is_free); +__attribute__((weak)) bool tlsf_check_hook(void *start, size_t size, bool is_free); + #if defined(__cplusplus) }; #endif From 0fcb10c71aa28854c5515417f4aefd2011de85d6 Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Tue, 9 Aug 2022 13:14:11 +0200 Subject: [PATCH 2/2] Remove the call to tlsf_assert in the tlsf_insist maccro In this commit: The call to tlsf_asssert is removed from tlsf_insist to allow the tlsf_check() function to return when one or more of the tlsf_insist() calls fails. In the previous implementation any failing tlsf_assist() was causing the tlsf_assert to terminate the execution of the application which doesn't allow the user to handle failures in tlsf_check() eventhough tlsf_check() returns a value. --- tlsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tlsf.c b/tlsf.c index 092553b..4255d10 100644 --- a/tlsf.c +++ b/tlsf.c @@ -618,7 +618,7 @@ typedef struct integrity_t int status; } integrity_t; -#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } } +#define tlsf_insist(x) { if (!(x)) { status--; } } static void integrity_walker(void* ptr, size_t size, int used, void* user) {