source: mainline/uspace/lib/c/generic/ubsan.c@ d73d992

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