1#include "sanitizer_common/sanitizer_atomic.h"
2
3#include <stdint.h>
4
5#if !SANITIZER_GPU
6#include <stdlib.h>
7#include <string.h>
8#endif
9
10#if defined(KERNEL_USE)
11extern "C" void ubsan_message(const char *msg);
12static void message(const char *msg) { ubsan_message(msg); }
13#elif SANITIZER_AMDGPU || SANITIZER_NVPTX
14// Manually declared until we hook up the C headers correctly.
15extern "C" {
16struct FILE;
17extern FILE *stderr;
18int fprintf(FILE *stream, const char *fmt, ...);
19}
20template <typename... Args>
21static void message(const char *msg, Args &&...args) {
22 fprintf(stderr, msg, args...);
23}
24#elif SANITIZER_SPIRV
25extern "C" int printf(const char *fmt, ...);
26template <typename... Args>
27static void message(const char *msg, Args &&...args) {
28 printf(msg, args...);
29}
30#else
31#include <unistd.h>
32static void message(const char *msg) { (void)write(fd: 2, buf: msg, n: strlen(s: msg)); }
33#endif
34
35// If for some reason we cannot build the runtime with preserve_all, don't
36// emit any symbol. Programs that need them will fail to link, but that is
37// better than randomly corrupted registers.
38// Some architectures don't support preserve_all (but clang still has the)
39// attribute. For now, only support x86-64 and aarch64.
40#if defined(__clang__) && defined(__has_cpp_attribute) && \
41 (defined(__x86_64__) || defined(__aarch64__))
42#if __has_cpp_attribute(clang::preserve_all)
43#define PRESERVE_HANDLERS true
44#else
45#define PRESERVE_HANDLERS false
46#endif
47#else
48#define PRESERVE_HANDLERS false
49#endif
50
51static const int kMaxCallerPcs = 20;
52static __sanitizer::atomic_uintptr_t caller_pcs[kMaxCallerPcs];
53// Number of elements in caller_pcs. A special value of kMaxCallerPcs + 1 means
54// that "too many errors" has already been reported.
55static __sanitizer::atomic_uint32_t caller_pcs_sz;
56
57static char *append_str(const char *s, char *buf, const char *end) {
58 for (const char *p = s; (buf < end) && (*p != '\0'); ++p, ++buf)
59 *buf = *p;
60 return buf;
61}
62
63static char *append_hex(uintptr_t d, char *buf, const char *end) {
64 // Print the address by nibbles.
65 for (unsigned shift = sizeof(uintptr_t) * 8; shift && buf < end;) {
66 shift -= 4;
67 unsigned nibble = (d >> shift) & 0xf;
68 *(buf++) = nibble < 10 ? nibble + '0' : nibble - 10 + 'a';
69 }
70 return buf;
71}
72
73static void format_msg(const char *kind, uintptr_t caller, char *buf,
74 const char *end) {
75 buf = append_str(s: "ubsan: ", buf, end);
76 buf = append_str(s: kind, buf, end);
77 buf = append_str(s: " by 0x", buf, end);
78 buf = append_hex(d: caller, buf, end);
79 buf = append_str(s: "\n", buf, end);
80 if (buf == end)
81 --buf; // Make sure we don't cause a buffer overflow.
82 *buf = '\0';
83}
84
85static void format(const char *kind, uintptr_t caller) {
86#if SANITIZER_GPU
87 (void)format_msg;
88 message("ubsan: %s by %p\n", kind, reinterpret_cast<void *>(caller));
89#else
90 char msg_buf[128];
91 format_msg(kind, caller, buf: msg_buf, end: msg_buf + sizeof(msg_buf));
92 message(msg: msg_buf);
93#endif
94}
95
96[[gnu::cold]] static void report_error(const char *kind, uintptr_t caller) {
97 if (caller == 0)
98 return;
99 while (true) {
100 unsigned sz = __sanitizer::atomic_load_relaxed(a: &caller_pcs_sz);
101 if (sz > kMaxCallerPcs)
102 return; // early exit
103 // when sz==kMaxCallerPcs print "too many errors", but only when cmpxchg
104 // succeeds in order to not print it multiple times.
105 if (sz > 0 && sz < kMaxCallerPcs) {
106 uintptr_t p;
107 for (unsigned i = 0; i < sz; ++i) {
108 p = __sanitizer::atomic_load_relaxed(a: &caller_pcs[i]);
109 if (p == 0)
110 break; // Concurrent update.
111 if (p == caller)
112 return;
113 }
114 if (p == 0)
115 continue; // FIXME: yield?
116 }
117
118 if (!__sanitizer::atomic_compare_exchange_strong(
119 a: &caller_pcs_sz, cmp: &sz, xchg: sz + 1, mo: __sanitizer::memory_order_seq_cst))
120 continue; // Concurrent update! Try again from the start.
121
122 if (sz == kMaxCallerPcs) {
123 message(msg: "ubsan: too many errors\n");
124 return;
125 }
126 __sanitizer::atomic_store_relaxed(a: &caller_pcs[sz], v: caller);
127
128 format(kind, caller);
129 }
130}
131
132SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error, const char *kind,
133 uintptr_t caller) {
134 report_error(kind, caller);
135}
136
137#if PRESERVE_HANDLERS
138SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_preserve,
139 const char *kind, uintptr_t caller)
140[[clang::preserve_all]] {
141 // Additional indirection so the user can override this with their own
142 // preserve_all function. This would allow, e.g., a function that reports the
143 // first error only, so for all subsequent calls we can skip the register save
144 // / restore.
145 __ubsan_report_error(kind, caller);
146}
147#endif
148
149SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_fatal, const char *kind,
150 uintptr_t caller) {
151 // Use another handlers, in case it's already overriden.
152 __ubsan_report_error(kind, caller);
153}
154
155static void NORETURN die() {
156#if SANITIZER_GPU
157 __builtin_verbose_trap("ubsan", "unrecoverable error");
158#else
159 abort();
160#endif
161}
162
163#if defined(__ANDROID__)
164extern "C" __attribute__((weak)) void android_set_abort_message(const char *);
165static void abort_with_message(const char *kind, uintptr_t caller) {
166 char msg_buf[128];
167 format_msg(kind, caller, msg_buf, msg_buf + sizeof(msg_buf));
168 if (&android_set_abort_message)
169 android_set_abort_message(msg_buf);
170 die();
171}
172#else
173static void abort_with_message(const char *, uintptr_t) { die(); }
174#endif
175
176#if SANITIZER_DEBUG
177namespace __sanitizer {
178// The DCHECK macro needs this symbol to be defined.
179void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
180 message("Sanitizer CHECK failed: ");
181 message(file);
182 message(":?? : "); // FIXME: Show line number.
183 message(cond);
184 die();
185}
186} // namespace __sanitizer
187#endif
188
189#define INTERFACE extern "C" __attribute__((visibility("default")))
190
191#if PRESERVE_HANDLERS
192#define HANDLER_PRESERVE(name, kind) \
193 INTERFACE void __ubsan_handle_##name##_minimal_preserve() \
194 [[clang::preserve_all]] { \
195 __ubsan_report_error_preserve(kind, GET_CALLER_PC()); \
196 }
197#else
198#define HANDLER_PRESERVE(name, kind)
199#endif
200
201#define HANDLER_RECOVER(name, kind) \
202 INTERFACE void __ubsan_handle_##name##_minimal() { \
203 __ubsan_report_error(kind, GET_CALLER_PC()); \
204 } \
205 HANDLER_PRESERVE(name, kind)
206
207#define HANDLER_NORECOVER(name, kind) \
208 INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
209 uintptr_t caller = GET_CALLER_PC(); \
210 __ubsan_report_error_fatal(kind, caller); \
211 abort_with_message(kind, caller); \
212 }
213
214#define HANDLER(name, kind) \
215 HANDLER_RECOVER(name, kind) \
216 HANDLER_NORECOVER(name, kind)
217
218HANDLER(type_mismatch, "type-mismatch")
219HANDLER(alignment_assumption, "alignment-assumption")
220HANDLER(add_overflow, "add-overflow")
221HANDLER(sub_overflow, "sub-overflow")
222HANDLER(mul_overflow, "mul-overflow")
223HANDLER(negate_overflow, "negate-overflow")
224HANDLER(divrem_overflow, "divrem-overflow")
225HANDLER(shift_out_of_bounds, "shift-out-of-bounds")
226HANDLER(out_of_bounds, "out-of-bounds")
227HANDLER(local_out_of_bounds, "local-out-of-bounds")
228HANDLER_RECOVER(builtin_unreachable, "builtin-unreachable")
229HANDLER_RECOVER(missing_return, "missing-return")
230HANDLER(vla_bound_not_positive, "vla-bound-not-positive")
231HANDLER(float_cast_overflow, "float-cast-overflow")
232HANDLER(load_invalid_value, "load-invalid-value")
233HANDLER(invalid_builtin, "invalid-builtin")
234HANDLER(invalid_objc_cast, "invalid-objc-cast")
235HANDLER(function_type_mismatch, "function-type-mismatch")
236HANDLER(implicit_conversion, "implicit-conversion")
237HANDLER(nonnull_arg, "nonnull-arg")
238HANDLER(nonnull_return, "nonnull-return")
239HANDLER(nullability_arg, "nullability-arg")
240HANDLER(nullability_return, "nullability-return")
241HANDLER(pointer_overflow, "pointer-overflow")
242HANDLER(cfi_check_fail, "cfi-check-fail")
243