mbedtls/tests/include/test/memory.h
David Horstmann d3efb92922 Add underflow check to UNPOISON counter decrement
Make sure that extra UNPOISON calls do not cause the poisoning counter
to underflow and wrap around.

Memory that is unpoisoned multiple times should remain unpoisoned.

Signed-off-by: David Horstmann <david.horstmann@arm.com>
2024-01-17 15:27:50 +00:00

108 lines
3.5 KiB
C

/**
* \file memory.h
*
* \brief Helper macros and functions related to testing memory management.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_MEMORY_H
#define TEST_MEMORY_H
#include "mbedtls/build_info.h"
#include "mbedtls/platform.h"
#include "test/helpers.h"
/** \def MBEDTLS_TEST_MEMORY_CAN_POISON
*
* This macro is defined if the tests are compiled with a method to mark
* memory as poisoned, which can be used to enforce some memory access
* policies.
*
* Support for the C11 thread_local keyword is also required.
*
* Currently, only Asan (Address Sanitizer) is supported.
*/
#if defined(MBEDTLS_TEST_HAVE_ASAN) && \
(__STDC_VERSION__ >= 201112L)
# define MBEDTLS_TEST_MEMORY_CAN_POISON
#endif
/** \def MBEDTLS_TEST_MEMORY_POISON(buf, size)
*
* Poison a memory area so that any attempt to read or write from it will
* cause a runtime failure.
*
* Depending on the implementation, this may poison a few bytes beyond the
* indicated region, but will never poison a separate object on the heap
* or a separate object with more than the alignment of a long long.
*
* The behavior is undefined if any part of the memory area is invalid.
*
* This is a no-op in builds without a poisoning method.
* See #MBEDTLS_TEST_MEMORY_CAN_POISON.
*
* \param buf Pointer to the beginning of the memory area to poison.
* \param size Size of the memory area in bytes.
*/
/** \def MBEDTLS_TEST_MEMORY_UNPOISON(buf, size)
*
* Undo the effect of #MBEDTLS_TEST_MEMORY_POISON.
*
* The behavior is undefined if any part of the memory area is invalid,
* or if the memory area contains a mixture of poisoned and unpoisoned parts.
*
* This is a no-op in builds without a poisoning method.
* See #MBEDTLS_TEST_MEMORY_CAN_POISON.
*
* \param buf Pointer to the beginning of the memory area to unpoison.
* \param size Size of the memory area in bytes.
*/
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
/** Thread-local variable used to enable memory poisoning. This is set and
* unset in the test wrappers so that calls to PSA functions from the library
* do not poison memory.
*/
extern _Thread_local unsigned int mbedtls_test_memory_poisoning_count;
/** Poison a memory area so that any attempt to read or write from it will
* cause a runtime failure.
*
* The behavior is undefined if any part of the memory area is invalid.
*/
void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size);
#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) \
do { \
mbedtls_test_memory_poisoning_count++; \
mbedtls_test_memory_poison(ptr, size); \
} while (0)
/** Undo the effect of mbedtls_test_memory_poison().
*
* This is a no-op if the given area is entirely valid, unpoisoned memory.
*
* The behavior is undefined if any part of the memory area is invalid,
* or if the memory area contains a mixture of poisoned and unpoisoned parts.
*/
void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size);
#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) \
do { \
mbedtls_test_memory_unpoison(ptr, size); \
if (mbedtls_test_memory_poisoning_count != 0) { \
mbedtls_test_memory_poisoning_count--; \
} \
} while (0)
#else /* MBEDTLS_TEST_MEMORY_CAN_POISON */
#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) ((void) (ptr), (void) (size))
#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) ((void) (ptr), (void) (size))
#endif /* MBEDTLS_TEST_MEMORY_CAN_POISON */
#endif /* TEST_MEMORY_H */