Memory checker fixes and enhancements. MISRA-related fixes.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15332 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2022-01-09 08:42:04 +00:00
parent 40fbc0044c
commit 6f221b1d4b
7 changed files with 117 additions and 38 deletions

View File

@ -668,6 +668,17 @@ struct nil_os_instance {
*/
#define MEM_NATURAL_ALIGN PORT_NATURAL_ALIGN
/**
* @brief Port-defined check on function pointers.
*
* @param[in] p function pointer to be checked
*/
#if defined(PORT_IS_VALID_FUNCTION) || defined(__DOXYGEN__)
#define MEM_IS_VALID_FUNCTION(p) PORT_IS_VALID_FUNCTION(p)
#else
#define MEM_IS_VALID_FUNCTION(p) true
#endif
/**
* @brief Alignment mask constant.
*

View File

@ -69,6 +69,13 @@ typedef struct {
/* External declarations. */
/*===========================================================================*/
#if !defined(__DOXYGEN__)
extern const memory_area_t __ch_mem_writable_areas[];
extern const memory_area_t __ch_mem_readable_areas[];
extern const memory_area_t __ch_mem_executable_areas[];
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -77,7 +84,7 @@ extern "C" {
const char *s,
size_t n);
bool chMemIsAreaContainedX(const memory_area_t areas[],
const void *base,
const void *p,
size_t size);
bool chMemIsAreaWritableX(void *p,
size_t size,
@ -85,6 +92,7 @@ extern "C" {
bool chMemIsAreaReadableX(const void *p,
size_t size,
unsigned align);
bool chMemIsAddressExecutableX(const void *p);
#endif
#ifdef __cplusplus
}
@ -100,23 +108,26 @@ extern "C" {
*
* @param[in] map pointer to a @p memory_area_t structure
* @param[in] p pointer to the area to be checked
* @param[in] size size of the area to be checked
* @param[in] size size of the area to be checked, zero is considered
* the whole address space
* @return The test result.
* @retval false if the area is entirely contained within one of the
* @retval true if the area is entirely contained within one of the
* specified areas.
* @retval true if the area check failed.
* @retval false if the area check failed.
*
* @xclass
*/
static inline bool chMemIsAreaWithinX(const memory_area_t *map,
const void *p,
size_t size) {
uint8_t *base = map->base;
uint8_t *end = base + map->size - (size_t)1;
const uint8_t *p8 = (const uint8_t *)p;
const uint8_t *mem_base = (const uint8_t *)map->base;
const uint8_t *mem_end = mem_base + map->size - (size_t)1;
const uint8_t *base = (const uint8_t *)p;
const uint8_t *end = base + size - (size_t)1;
return (bool)((p8 >= base) && (p8 <= end) &&
(size <= (size_t)(end - p8) + (size_t)1));
chDbgAssert(mem_base <= mem_end, "invalid memory area");
return (bool)((base <= end) && (base >= mem_base) && (end <= mem_end));
}
#if CH_CFG_USE_MEMCHECKS == FALSE
@ -130,7 +141,7 @@ bool chMemIsAreaWritableX(const void *p,
(void)size;
(void)align;
return false;
return true;
}
bool chMemIsAreaReadableX(const void *p,
@ -141,7 +152,14 @@ bool chMemIsAreaReadableX(const void *p,
(void)size;
(void)align;
return false;
return true;
}
bool chMemIsAddressExecutableX(const void *p) {
(void)p;
return true;
}
#endif

View File

@ -42,7 +42,7 @@
* writable areas array for the device in use.
* @note The array is terminated by an end marker (base=-1).
*/
CC_WEAK memory_area_t __ch_mem_writable_areas[] = {
CC_WEAK const memory_area_t __ch_mem_writable_areas[] = {
{(uint8_t *)0, 0U}, /* Whole space is writable.*/
{(uint8_t *)-1, 0U},
};
@ -53,7 +53,18 @@ CC_WEAK memory_area_t __ch_mem_writable_areas[] = {
* readable areas array for the device in use.
* @note The array is terminated by an end marker (base=-1).
*/
CC_WEAK memory_area_t __ch_mem_readable_areas[] = {
CC_WEAK const memory_area_t __ch_mem_readable_areas[] = {
{(uint8_t *)0, 0U}, /* Whole space is readable.*/
{(uint8_t *)-1, 0U},
};
/**
* @brief Default executable memory areas.
* @details By default all memory is executable, user must provide its own
* executable areas array for the device in use.
* @note The array is terminated by an end marker (base=-1).
*/
CC_WEAK const memory_area_t __ch_mem_executable_areas[] = {
{(uint8_t *)0, 0U}, /* Whole space is readable.*/
{(uint8_t *)-1, 0U},
};
@ -85,9 +96,9 @@ CC_WEAK memory_area_t __ch_mem_readable_areas[] = {
* @param[in] s pointer to the string to be checked
* @param[in] n maximum expected size of the string
* @return The test result.
* @retval false if the string is entirely contained within one of the
* @retval true if the string is entirely contained within one of the
* specified areas.
* @retval true if the string check failed.
* @retval false if the string check failed.
*
* @xclass
*/
@ -116,11 +127,12 @@ bool chMemIsStringWithinX(const memory_area_t *map, const char *s, size_t n) {
* @param[in] map array of valid areas terminated with an end
* marker (base=-1)
* @param[in] p pointer to the area to be checked
* @param[in] size size of the area to be checked
* @param[in] size size of the area to be checked, zero is considered
* the whole address space
* @return The test result.
* @retval false if the area is entirely contained within one of the
* @retval true if the area is entirely contained within one of the
* specified areas.
* @retval true if the area check failed.
* @retval false if the area check failed.
*
* @xclass
*/
@ -148,19 +160,18 @@ bool chMemIsAreaContainedX(const memory_area_t areas[],
* @brief Memory writable area check.
* @details Checks if specified pointer belongs to one of the system-defined
* writable areas and is aligned as specified.
* @note This function is only effective if @p CH_CFG_SYS_WRITABLE_REGIONS
* is defined, if it is not defined then just the alignment of
* the pointer is checked.
* @note @p __ch_mem_writable_areas must be the name of a global
* @p memory_area_t array terminated with an end marker (-1, 0).
*
* @param[in] p pointer to the area to be checked
* @param[in] size size of the area to be checked, zero is considered
* the whole address space
* @param[in] align required pointer alignment to be checked, must be
* a power of two
* @return The test result.
* @retval false if the area is entirely contained within one of the
* @retval true if the area is entirely contained within one of the
* system-defined writable areas.
* @retval true if the area check failed.
* @retval false if the area check failed.
*
* @xclass
*/
@ -171,7 +182,7 @@ bool chMemIsAreaWritableX(void *p,
chDbgCheck((align & (align - 1U)) == 0U);
if (!MEM_IS_ALIGNED(p, align)) {
return true;
return false;
}
return chMemIsAreaContainedX(__ch_mem_writable_areas, p, size);
@ -181,19 +192,18 @@ bool chMemIsAreaWritableX(void *p,
* @brief Memory readable area check.
* @details Checks if specified pointer belongs to one of the system-defined
* readable areas and is aligned as specified.
* @note This function is only effective if @p CH_CFG_SYS_READABLE_REGIONS
* is defined, if it is not defined then just the alignment of
* the pointer is checked.
* @note @p __ch_mem_readable_areas must be the name of a global
* @p memory_area_t array terminated with an end marker (-1, 0).
*
* @param[in] p pointer to the area to be checked
* @param[in] size size of the area to be checked, zero is considered
* the whole address space
* @param[in] align required pointer alignment to be checked, must be
* a power of two
* @return The test result.
* @retval false if the area is entirely contained within one of the
* @retval true if the area is entirely contained within one of the
* system-defined readable areas.
* @retval true if the area check failed.
* @retval false if the area check failed.
*
* @xclass
*/
@ -204,12 +214,38 @@ bool chMemIsAreaReadableX(const void *p,
chDbgCheck((align & (align - 1U)) == 0U);
if (!MEM_IS_ALIGNED(p, align)) {
return true;
return false;
}
return chMemIsAreaContainedX(__ch_mem_readable_areas, p, size);
}
/**
* @brief Memory executable area check.
* @details Checks if specified pointer belongs to one of the system-defined
* executable areas and is aligned properly.
* @note @p __ch_mem_executable_areas must be the name of a global
* @p memory_area_t array terminated with an end marker (-1, 0).
*
* @param[in] p pointer to the area to be checked
* @return The test result.
* @retval true if the address belongs to one of the
* system-defined executable areas.
* @retval false if the address check failed.
*
* @xclass
*/
bool chMemIsAddressExecutableX(const void *p) {
/*lint -save -e506 -e774 [2.1, 14.3] It can be a constant by design.*/
if (!MEM_IS_VALID_FUNCTION(p)) {
/*lint -restore*/
return false;
}
return chMemIsAreaContainedX(__ch_mem_executable_areas, p, 1);
}
#endif /* CH_CFG_USE_MEMCHECKS == TRUE */
/** @} */

View File

@ -399,8 +399,6 @@ size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp) {
return n;
}
#define isvalidfunction(p) true
/**
* @brief Heap integrity check.
* @details Performs an integrity check of a heap stucture.
@ -423,8 +421,10 @@ bool chHeapIntegrityCheck(memory_heap_t *heapp) {
}
/* Validating heap object.*/
if ((heapp->provider != NULL) && !isvalidfunction(heapp->provider)) {
return true;
if (heapp->provider != NULL) {
if (!chMemIsAddressExecutableX(heapp->provider)) {
return true;
}
}
/* Taking heap mutex.*/

View File

@ -58,14 +58,25 @@
* @note Represents the required alignment for integer and pointer
* data types.
*/
#define MEM_NATURAL_ALIGN PORT_NATURAL_ALIGN
#define MEM_NATURAL_ALIGN PORT_NATURAL_ALIGN
/**
* @brief Port-defined check on function pointers.
*
* @param[in] p function pointer to be checked
*/
#if defined(PORT_IS_VALID_FUNCTION) || defined(__DOXYGEN__)
#define MEM_IS_VALID_FUNCTION(p) PORT_IS_VALID_FUNCTION(p)
#else
#define MEM_IS_VALID_FUNCTION(p) true
#endif
/**
* @brief Alignment mask constant.
*
* @param[in] a alignment, must be a power of two
*/
#define MEM_ALIGN_MASK(a) ((size_t)(a) - 1U)
#define MEM_ALIGN_MASK(a) ((size_t)(a) - 1U)
/**
* @brief Aligns to the previous aligned memory address.
@ -95,7 +106,7 @@
* @param[in] p variable to be aligned
* @param[in] a alignment, must be a power of two
*/
#define MEM_IS_ALIGNED(p, a) (((size_t)(p) & MEM_ALIGN_MASK(a)) == 0U)
#define MEM_IS_ALIGNED(p, a) (((size_t)(p) & MEM_ALIGN_MASK(a)) == 0U)
/**
* @brief Returns whatever a constant is a valid alignment.

View File

@ -521,8 +521,11 @@ static inline sysinterval_t chTimeStampDiffX(systimestamp_t start,
/* Time difference as a wide time stamp.*/
diff = end - start;
/*lint -save -e685 [14.3] This condition becomes always true when both
types have the same width, it is fine, this is an assertion.*/
chDbgAssert(diff <= (systimestamp_t)((sysinterval_t)-1),
"conversion overflow");
/*lint -restore*/
/*lint -save -e9033 [10.8] This cast is required by the operation, it is
known that the destination type can be wider.*/

View File

@ -54,7 +54,7 @@
*
* @notapi
*/
NOINLINE static void trace_next(os_instance_t *oip) {
static NOINLINE void trace_next(os_instance_t *oip) {
oip->trace_buffer.ptr->time = chVTGetSystemTimeX();
#if PORT_SUPPORTS_RT == TRUE