summaryrefslogtreecommitdiff
path: root/lib/sbi/tests/sbi_ubsan_test.c
blob: 23409cb1628d91e2232a4bbb1831d9275f32a3b1 (plain)
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
/*
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Author: Marcos Oduardo <[email protected]>
 */

#include <sbi/sbi_unit_test.h>
#include <sbi/sbi_types.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_ubsan.h>

#define UBSAN_EXPECT_FIRES(test, stmt)                                    \
	do {                                                              \
		unsigned long _before = sbi_ubsan_report_count;           \
		stmt;                                                     \
		SBIUNIT_EXPECT_NE(test, sbi_ubsan_report_count, _before); \
	} while (0)

static void test_ubsan_add_overflow(struct sbiunit_test_case *test)
{
	volatile int a = 0x7FFFFFFF; //INT_MAx
	volatile int b = 1;
	volatile int c;
	UBSAN_EXPECT_FIRES(test, c = a + b);
	(void)c;
}

static void test_ubsan_sub_overflow(struct sbiunit_test_case *test)
{
	volatile int a = 0x80000000; //INT_MIN
	volatile int b = 1;
	volatile int c;
	UBSAN_EXPECT_FIRES(test, c = a - b);
	(void)c;
}

static void test_ubsan_mul_overflow(struct sbiunit_test_case *test)
{
	volatile int a = 0x7FFFFFFF;
	volatile int b = 2;
	volatile int c;
	UBSAN_EXPECT_FIRES(test, c = a * b);
	(void)c;
}

static void test_ubsan_divrem(struct sbiunit_test_case *test)
{
	volatile int a = 10;
	volatile int b = 0;
	volatile int c;
	UBSAN_EXPECT_FIRES(test, c = a / b);
	(void)c;
}

static void test_ubsan_oob(struct sbiunit_test_case *test)
{
	volatile int idx = 5;
	int arr[3]	 = { 1, 2, 3 };
	volatile int val;
	UBSAN_EXPECT_FIRES(test, val = arr[idx]);
	(void)val;
}

static void test_ubsan_shift_too_large(struct sbiunit_test_case *test)
{
	volatile unsigned long val = 1;
	volatile int shift	   = 64;
	volatile unsigned long res;
	UBSAN_EXPECT_FIRES(test, res = val << shift);
	(void)res;
}

static void test_ubsan_shift_negative(struct sbiunit_test_case *test)
{
	volatile int val   = 1;
	volatile int shift = -1;
	volatile int res;

	UBSAN_EXPECT_FIRES(test, res = val << shift);
	(void)res;
}

static void test_ubsan_load_invalid_bool(struct sbiunit_test_case *test)
{
	volatile char bool_val = 5;
	volatile bool *b_ptr   = (bool *)&bool_val;
	volatile int taken     = 0;
	UBSAN_EXPECT_FIRES(test, if (*b_ptr) taken = 1);
	(void)taken;
}

static void test_ubsan_pointer_overflow(struct sbiunit_test_case *test)
{
	volatile uintptr_t base = 0xFFFFFFFFFFFFFFFEUL;
	volatile char *ptr	= (char *)base;
	volatile char *res;
	UBSAN_EXPECT_FIRES(test, res = ptr + 5);
	(void)res;
}

static struct sbiunit_test_case ubsan_tests[] = {
	SBIUNIT_TEST_CASE(test_ubsan_add_overflow),
	SBIUNIT_TEST_CASE(test_ubsan_sub_overflow),
	SBIUNIT_TEST_CASE(test_ubsan_mul_overflow),
	SBIUNIT_TEST_CASE(test_ubsan_divrem),
	SBIUNIT_TEST_CASE(test_ubsan_oob),
	SBIUNIT_TEST_CASE(test_ubsan_shift_too_large),
	SBIUNIT_TEST_CASE(test_ubsan_shift_negative),
	SBIUNIT_TEST_CASE(test_ubsan_load_invalid_bool),
	SBIUNIT_TEST_CASE(test_ubsan_pointer_overflow),
	SBIUNIT_END_CASE,
};

SBIUNIT_TEST_SUITE(ubsan_test_suite, ubsan_tests);