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