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