/ tests / lib / stack-test.c
stack-test.c
  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  
 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.  */
 30  static void clean_stack(void)
 31  {
 32  	fill_stack(STACK_GUARD_VALUE);
 33  }
 34  
 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  
 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  
 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  
 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  
 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  
 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  
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  
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  }