| /* 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); |
| } |