1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/* SPDX-License-Identifier: GPL-2.0-only */
#include <tests/test.h>
#include <lib.h>
#include <symbols.h>
#if CONFIG_STACK_SIZE == 0
#define STACK_SIZE 0x1000
#else
#define STACK_SIZE CONFIG_STACK_SIZE
#endif
/* Value used for stack initialization. Change if implementation changes. */
#define STACK_GUARD_VALUE 0xDEADBEEF
__weak extern u8 _stack[];
__weak extern u8 _estack[];
TEST_REGION(stack, STACK_SIZE);
static void fill_stack(u32 value)
{
u32 *stack = (u32 *)_stack;
for (size_t i = 0; i < STACK_SIZE / sizeof(u32); ++i)
stack[i] = value;
}
/* Fill stack region with guard value. */
static void clean_stack(void)
{
fill_stack(STACK_GUARD_VALUE);
}
static int setup_stack_test(void **state)
{
void *top_of_stack = _stack + sizeof(_stack);
clean_stack();
*state = top_of_stack;
return 0;
}
static void test_empty_stack(void **state)
{
void *top_of_stack = *state;
/* Expect success when checking empty stack. */
assert_int_equal(0, checkstack(top_of_stack, 0));
}
static void test_almost_full_stack(void **state)
{
void *top_of_stack = *state;
u32 *stack = (u32 *)_stack;
/* Fill stack with random value except last word */
for (size_t i = 1; i < STACK_SIZE / sizeof(u32); ++i)
stack[i] = 0xAA11FF44;
/* Expect success when checking almost-full stack,
because last guard value is present */
assert_int_equal(0, checkstack(top_of_stack, 0));
}
static void test_full_stack(void **state)
{
void *top_of_stack = *state;
/* Fill stack with value different than stack guard */
fill_stack(0x600DB015);
/* Expect failure when checking full stack as absence of guard value at the end of
the stack indicates stack overrun. */
expect_assert_failure(checkstack(top_of_stack, 0));
}
static void test_partialy_filled_stack(void **state)
{
void *top_of_stack = *state;
u32 *stack = (u32 *)_stack;
size_t i = STACK_SIZE / sizeof(u32) / 2;
for (; i < STACK_SIZE / sizeof(u32); ++i)
stack[i] = 0x4321ABDC + i;
/* Expect success when checking partially-filled stack,
because only part of stack is filled with non-guard value. */
assert_int_equal(0, checkstack(top_of_stack, 0));
}
static void test_alternately_filled_stack(void **state)
{
void *top_of_stack = *state;
u32 *stack = (u32 *)_stack;
size_t i;
for (i = 0; i < STACK_SIZE / sizeof(u32); i += 2)
stack[i] = STACK_GUARD_VALUE;
for (i = 1; i < STACK_SIZE / sizeof(u32); i += 2)
stack[i] = 0x42420707;
assert_int_equal(0, checkstack(top_of_stack, 0));
}
static void test_incorrectly_initialized_stack(void **state)
{
void *top_of_stack = *state;
u32 *stack = (u32 *)_stack;
/* Remove last stack guard value */
stack[0] = 0xFF00FF11;
/* Expect failure when there is no last stack guard value even if no other value was
changed. */
expect_assert_failure(checkstack(top_of_stack, 0));
}
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup(test_empty_stack, setup_stack_test),
cmocka_unit_test_setup(test_almost_full_stack, setup_stack_test),
cmocka_unit_test_setup(test_full_stack, setup_stack_test),
cmocka_unit_test_setup(test_partialy_filled_stack, setup_stack_test),
cmocka_unit_test_setup(test_alternately_filled_stack, setup_stack_test),
cmocka_unit_test_setup(test_incorrectly_initialized_stack, setup_stack_test),
};
return cb_run_group_tests(tests, NULL, NULL);
}
|