mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
3b9450b59d
This commit updates the tlsf submodule to include the modification made in the component aiming to perform integrity check on all blocks (not only the free ones). Added test to test the fix in test_apps/heap_tests. Fixes https://github.com/espressif/esp-idf/issues/12231
115 lines
4.0 KiB
C
115 lines
4.0 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
|
*/
|
|
#include "unity.h"
|
|
#include "stdio.h"
|
|
|
|
#include "esp_heap_caps.h"
|
|
|
|
/* executing multi_heap_internal_check_block_poisoning()
|
|
* takes longer on external RAM and therefore the timeout
|
|
* in the test of 30 seconds is exceeded. Execute the test
|
|
* on a smaller memory chunk
|
|
*/
|
|
#ifdef CONFIG_SPIRAM
|
|
const size_t MALLOC_SIZE = 16;
|
|
#else
|
|
const size_t MALLOC_SIZE = 64;
|
|
#endif
|
|
const uint8_t CORRUPTED_VALUE = 0xaa;
|
|
|
|
/* This test will corrupt the memory of a free block in the heap and check
|
|
* that in the case of comprehensive poisoning the heap corruption is detected
|
|
* by heap_caps_check_integrity(). For light poisoning and no poisoning, the test will
|
|
* check that heap_caps_check_integrity() does not report the corruption.
|
|
*/
|
|
TEST_CASE("multi_heap poisoning detection", "[heap]")
|
|
{
|
|
/* malloc some memory to get a pointer */
|
|
uint8_t *ptr = heap_caps_malloc(MALLOC_SIZE, MALLOC_CAP_8BIT);
|
|
|
|
/* free the memory to free the block but keep the pointer in mind */
|
|
heap_caps_free(ptr);
|
|
|
|
/* variable used in the test */
|
|
uint8_t original_value = 0x00;
|
|
|
|
for (size_t i = 0; i < MALLOC_SIZE; i++)
|
|
{
|
|
/* keep the good value in store in order to check that when we set the byte back
|
|
* to its original value, heap_caps_check_integrity() no longer returns the
|
|
* heap corruption. */
|
|
original_value = ptr[i];
|
|
|
|
/* set corrupted value in the free memory*/
|
|
ptr[i] = CORRUPTED_VALUE;
|
|
|
|
bool is_heap_ok = heap_caps_check_integrity(MALLOC_CAP_8BIT, true);
|
|
#ifdef CONFIG_HEAP_POISONING_COMPREHENSIVE
|
|
/* check that heap_caps_check_integrity() detects the corruption */
|
|
TEST_ASSERT_FALSE(is_heap_ok);
|
|
#else
|
|
/* the comprehensive corruption is not checked in the heap_caps_check_integrity() */
|
|
TEST_ASSERT_TRUE(is_heap_ok);
|
|
#endif
|
|
/* fix the corruption by restoring the original value at ptr + i */
|
|
ptr[i] = original_value;
|
|
|
|
/* check that heap_caps_check_integrity() stops reporting the corruption */
|
|
is_heap_ok = heap_caps_check_integrity(MALLOC_CAP_8BIT, true);
|
|
TEST_ASSERT_TRUE(is_heap_ok);
|
|
}
|
|
}
|
|
|
|
#if !defined(CONFIG_HEAP_TLSF_USE_ROM_IMPL)
|
|
|
|
#ifdef CONFIG_HEAP_TASK_TRACKING
|
|
#define HEAD_CANARY_OFFSET 3 // head canary | task tracking | allocated size
|
|
#else
|
|
#define HEAD_CANARY_OFFSET 2 // head canary | allocated size
|
|
#endif // CONFIG_HEAP_TASK_TRACKING
|
|
|
|
#define TAIL_CANARY_OFFSET 1
|
|
|
|
/* This test will corrupt the canary of a allocated memory block and call the
|
|
* heap_caps_check_integrity() function to check that the corruption is detected.
|
|
*/
|
|
TEST_CASE("canary corruption in light or comprehensive poisoning mode", "[heap]")
|
|
{
|
|
const uint8_t allocation_size = 1 * sizeof(uint32_t);
|
|
/* malloc some memory to get a pointer */
|
|
uint32_t *ptr = heap_caps_malloc(allocation_size, MALLOC_CAP_DEFAULT);
|
|
TEST_ASSERT_NOT_NULL(ptr);
|
|
|
|
/* corrupt the head canary */
|
|
uint32_t canary = ptr[-HEAD_CANARY_OFFSET];
|
|
ptr[-HEAD_CANARY_OFFSET] = 0xdeadbeef;
|
|
|
|
/* call the integrity check function and verify that it returns 0 (corruption detected) */
|
|
bool is_corrupted = !heap_caps_check_integrity(MALLOC_CAP_DEFAULT, false);
|
|
TEST_ASSERT_TRUE(is_corrupted);
|
|
|
|
/* fix the head canary */
|
|
ptr[-HEAD_CANARY_OFFSET] = canary;
|
|
|
|
/* re run the corruption check to make sure the function returns no corruption */
|
|
is_corrupted = !heap_caps_check_integrity(MALLOC_CAP_DEFAULT, false);
|
|
TEST_ASSERT_FALSE(is_corrupted);
|
|
|
|
/* corrupt tail canary */
|
|
canary = ptr[TAIL_CANARY_OFFSET];
|
|
ptr[TAIL_CANARY_OFFSET] = 0xdeadbeef;
|
|
|
|
/* call the integrity check function and verify that it returns 0 (corruption detected) */
|
|
is_corrupted = !heap_caps_check_integrity(MALLOC_CAP_DEFAULT, false);
|
|
TEST_ASSERT_TRUE(is_corrupted);
|
|
|
|
/* clear the corruption and free the pointer before returning */
|
|
ptr[TAIL_CANARY_OFFSET] = canary;
|
|
heap_caps_free(ptr);
|
|
}
|
|
|
|
#endif // !CONFIG_HEAP_TLSF_USE_ROM_IMPL
|