source: mainline/kernel/generic/src/lib/ubsan.c@ 2f7d77c6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2f7d77c6 was 2f7d77c6, checked in by Jiří Zárevúcky <jiri.zarevucky@…>, 7 years ago

Add rudimentary support for undefined behavior sanitizer.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright (c) 2016, Linaro Limited
4 */
5
6/* Modified for HelenOS use by Jiří Zárevúcky. */
7
8#include <stdbool.h>
9#include <stdint.h>
10#include <stddef.h>
11#include <panic.h>
12#include <mem.h>
13
14#define PRINTF(...) printf(__VA_ARGS__)
15#define ubsan_panic() panic("... aborting ...")
16
17struct source_location {
18 const char *file_name;
19 uint32_t line;
20 uint32_t column;
21};
22
23struct type_descriptor {
24 uint16_t type_kind;
25 uint16_t type_info;
26 char type_name[];
27};
28
29struct type_mismatch_data {
30 struct source_location loc;
31 struct type_descriptor *type;
32 unsigned long alignment;
33 unsigned char type_check_kind;
34};
35
36struct overflow_data {
37 struct source_location loc;
38 struct type_descriptor *type;
39};
40
41struct shift_out_of_bounds_data {
42 struct source_location loc;
43 struct type_descriptor *lhs_type;
44 struct type_descriptor *rhs_type;
45};
46
47struct out_of_bounds_data {
48 struct source_location loc;
49 struct type_descriptor *array_type;
50 struct type_descriptor *index_type;
51};
52
53struct unreachable_data {
54 struct source_location loc;
55};
56
57struct vla_bound_data {
58 struct source_location loc;
59 struct type_descriptor *type;
60};
61
62struct invalid_value_data {
63 struct source_location loc;
64 struct type_descriptor *type;
65};
66
67struct nonnull_arg_data {
68 struct source_location loc;
69};
70
71struct nonnull_return_data {
72 struct source_location loc;
73 struct source_location attr_loc;
74};
75
76/*
77 * When compiling with -fsanitize=undefined the compiler expects functions
78 * with the following signatures. The functions are never called directly,
79 * only when undefined behavior is detected in instrumented code.
80 */
81void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, unsigned long ptr);
82void __ubsan_handle_add_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
83void __ubsan_handle_sub_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
84void __ubsan_handle_mul_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
85void __ubsan_handle_negate_overflow(struct overflow_data *data, unsigned long old_val);
86void __ubsan_handle_divrem_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
87void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, unsigned long lhs, unsigned long rhs);
88void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, unsigned long idx);
89void __ubsan_handle_unreachable(struct unreachable_data *data);
90void __ubsan_handle_missing_return(struct unreachable_data *data);
91void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, unsigned long bound);
92void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, unsigned long val);
93#if __GCC_VERSION < 60000
94void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no);
95#else
96void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data);
97#endif
98void __ubsan_handle_nonnull_return(struct nonnull_return_data *data);
99
100static void print_loc(const char *func, struct source_location *loc)
101{
102 const char *f = func;
103 const char func_prefix[] = "__ubsan_handle";
104
105 if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1))
106 f += sizeof(func_prefix);
107
108 PRINTF("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32 "\n",
109 f, loc->file_name, loc->line, loc->column);
110}
111
112void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
113 unsigned long ptr)
114{
115 print_loc(__func__, &data->loc);
116 ubsan_panic();
117}
118
119void __ubsan_handle_add_overflow(struct overflow_data *data,
120 unsigned long lhs,
121 unsigned long rhs)
122{
123 print_loc(__func__, &data->loc);
124 ubsan_panic();
125}
126
127void __ubsan_handle_sub_overflow(struct overflow_data *data,
128 unsigned long lhs,
129 unsigned long rhs)
130{
131 print_loc(__func__, &data->loc);
132 ubsan_panic();
133}
134
135void __ubsan_handle_mul_overflow(struct overflow_data *data,
136 unsigned long lhs,
137 unsigned long rhs)
138{
139 print_loc(__func__, &data->loc);
140 ubsan_panic();
141}
142
143void __ubsan_handle_negate_overflow(struct overflow_data *data,
144 unsigned long old_val)
145{
146 print_loc(__func__, &data->loc);
147 ubsan_panic();
148}
149
150void __ubsan_handle_divrem_overflow(struct overflow_data *data,
151 unsigned long lhs,
152 unsigned long rhs)
153{
154 print_loc(__func__, &data->loc);
155 ubsan_panic();
156}
157
158void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
159 unsigned long lhs,
160 unsigned long rhs)
161{
162 print_loc(__func__, &data->loc);
163 PRINTF("LHS type: %s, value: %lu, RHS type: %s, value: %lu\n",
164 data->lhs_type->type_name, lhs, data->rhs_type->type_name, rhs);
165 ubsan_panic();
166}
167
168void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
169 unsigned long idx)
170{
171 print_loc(__func__, &data->loc);
172 ubsan_panic();
173}
174
175void __ubsan_handle_unreachable(struct unreachable_data *data)
176{
177 print_loc(__func__, &data->loc);
178 ubsan_panic();
179}
180
181void __ubsan_handle_missing_return(struct unreachable_data *data)
182{
183 print_loc(__func__, &data->loc);
184 ubsan_panic();
185}
186
187void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
188 unsigned long bound)
189{
190 print_loc(__func__, &data->loc);
191 ubsan_panic();
192}
193
194void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
195 unsigned long val)
196{
197 print_loc(__func__, &data->loc);
198 ubsan_panic();
199}
200
201#if __GCC_VERSION < 60000
202void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no)
203{
204 print_loc(__func__, &data->loc);
205 ubsan_panic();
206}
207#else
208void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
209{
210 print_loc(__func__, &data->loc);
211 ubsan_panic();
212}
213#endif
214
215void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
216{
217 print_loc(__func__, &data->loc);
218 ubsan_panic();
219}
Note: See TracBrowser for help on using the repository browser.