mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-30 20:51:41 +00:00 
			
		
		
		
	 39f789df93
			
		
	
	39f789df93
	
	
	
		
			
			modify existing patch of TLSF rom and add multi heap patch to add the walker feature to the ROM implementation of the heap component.
		
			
				
	
	
		
			102 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
 | |
|  *
 | |
|  * SPDX-License-Identifier: Unlicense OR CC0-1.0
 | |
|  */
 | |
| #include "unity.h"
 | |
| #include "stdio.h"
 | |
| 
 | |
| #include "esp_heap_caps.h"
 | |
| #include "esp_rom_sys.h"
 | |
| #define PASS_CODE 0x9876BAAB
 | |
| #define ALLOC_SIZE 16
 | |
| 
 | |
| static void calculate_block_metadata_size(size_t *header, size_t *footer)
 | |
| {
 | |
|     *header = 0;
 | |
|     *footer = 0;
 | |
| #if !CONFIG_HEAP_POISONING_DISABLED
 | |
|     *header += 8; // sizeof(poison_head_t)
 | |
|     *footer += 4; // sizeof(poison_tail_t)
 | |
| #endif
 | |
| #if CONFIG_HEAP_TASK_TRACKING
 | |
|     *header += 4; // sizeof(TaskHandle_t)
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static bool block_found = false;
 | |
| static bool heap_corrupted = false;
 | |
| static bool heap_walker(walker_heap_into_t heap_info, walker_block_info_t block_info, void* user_data)
 | |
| {
 | |
|     if ((intptr_t)heap_info.end - (intptr_t)block_info.ptr < block_info.size)
 | |
|     {
 | |
|         heap_corrupted = true;
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     TEST_ASSERT(*(uint32_t*)user_data == PASS_CODE);
 | |
|     TEST_ASSERT_NOT_NULL(block_info.ptr);
 | |
| 
 | |
|     size_t metadata_size_head = 0;
 | |
|     size_t metadata_size_tail = 0;
 | |
|     calculate_block_metadata_size(&metadata_size_head, &metadata_size_tail);
 | |
| 
 | |
|     /* look for the first 4 bytes pass code to identify the memory allocated in the test */
 | |
|     const uint32_t pass_code = *((uint32_t*)block_info.ptr + (metadata_size_head / sizeof(uint32_t)));
 | |
|     if (pass_code == PASS_CODE) {
 | |
|         TEST_ASSERT(block_info.size == ALLOC_SIZE + metadata_size_head + metadata_size_tail);
 | |
|         TEST_ASSERT_TRUE(block_info.used);
 | |
|         block_found = true;
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| /* This test assures the proper functioning of heap_caps_walk and heap_caps_walk_all
 | |
|  * when a corruption occurs in a random heap. The callback which detects the corruption
 | |
|  * returns false to the walker which should result in the interruption of the heap traversal
 | |
|  * by the walker instead of a crash.
 | |
|  */
 | |
| TEST_CASE("heap walker", "[heap]")
 | |
| {
 | |
|     /* Allocate memory using the MALLOC_CAP_DEFAULT capability */
 | |
|     void *default_ptr = heap_caps_malloc(ALLOC_SIZE, MALLOC_CAP_DEFAULT);
 | |
|     TEST_ASSERT_NOT_NULL(default_ptr);
 | |
| 
 | |
|     /* Write the pass code in the first word of the allocated memory */
 | |
|     *((uint32_t*)default_ptr) = (uint32_t)PASS_CODE;
 | |
| 
 | |
|     /* call the heap_caps_walker to make sure the hook function is triggered
 | |
|      * and check that the allocated memory is found while walking the heap */
 | |
|     uint32_t user_code = PASS_CODE;
 | |
|     heap_caps_walk_all(heap_walker, &user_code);
 | |
|     TEST_ASSERT_TRUE(block_found);
 | |
| }
 | |
| 
 | |
| /* This test assures the proper functioning of heap_caps_walk and heap_caps_walk_all
 | |
|  */
 | |
| TEST_CASE("heap walker corrupted heap detection", "[heap]")
 | |
| {
 | |
|     /* Allocate memory using the MALLOC_CAP_DEFAULT capability */
 | |
|     void *default_ptr = heap_caps_malloc(ALLOC_SIZE, MALLOC_CAP_DEFAULT);
 | |
|     TEST_ASSERT_NOT_NULL(default_ptr);
 | |
| 
 | |
|     size_t metadata_size_head = 0;
 | |
|     size_t metadata_size_tail = 0;
 | |
|     calculate_block_metadata_size(&metadata_size_head, &metadata_size_tail);
 | |
|     (void)metadata_size_tail;
 | |
| 
 | |
|     /* corrupting the size field of the block metadata with a size bigger
 | |
|      * than the heap itself */
 | |
|     *((uint32_t*)default_ptr - (metadata_size_head / 4) - 1) = 0xFF000000;
 | |
| 
 | |
|     /* Write the pass code in the first word of the allocated memory */
 | |
|     *((uint32_t*)default_ptr) = (uint32_t)PASS_CODE;
 | |
| 
 | |
|     /* call the heap_caps_walker to make sure the hook function is triggered
 | |
|      * and check that the allocated memory is found while walking the heap */
 | |
|     uint32_t user_code = PASS_CODE;
 | |
|     heap_caps_walk_all(heap_walker, &user_code);
 | |
|     TEST_ASSERT_TRUE(heap_corrupted);
 | |
| }
 |