]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/kern_ubsan.c
Remove spurious newline
[FreeBSD/FreeBSD.git] / sys / kern / kern_ubsan.c
1 /*      $NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $  */
2
3 /*-
4  * Copyright (c) 2018 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28
29
30 /*
31  * The micro UBSan implementation for the userland (uUBSan) and kernel (kUBSan).
32  * The uBSSan versions is suitable for inclusion into libc or used standalone
33  * with ATF tests.
34  *
35  * This file due to long symbol names generated by a compiler during the
36  * instrumentation process does not follow the KNF style with 80-column limit.
37  */
38
39 #include <sys/cdefs.h>
40 #ifdef __FreeBSD__
41 __FBSDID("$FreeBSD$");
42 #else
43 #if defined(_KERNEL)
44 __KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
45 #else
46 __RCSID("$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
47 #endif
48 #endif
49
50 #if defined(_KERNEL)
51 #include <sys/param.h>
52 #include <sys/types.h>
53 #include <sys/limits.h>
54 #include <sys/systm.h>
55 #include <machine/_inttypes.h>
56 #include <machine/stdarg.h>
57 #define ASSERT(x) KASSERT(x, ("%s: " __STRING(x) " failed", __func__))
58 #define __arraycount(x) nitems(x)
59 #define ISSET(x, y)     ((x) & (y))
60 #define __BIT(x)        ((uintmax_t)1 << (uintmax_t)(x))
61 #define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
62 #define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
63 #else
64 #if defined(_LIBC)
65 #include "namespace.h"
66 #endif
67 #include <sys/param.h>
68 #include <assert.h>
69 #include <inttypes.h>
70 #include <math.h>
71 #include <signal.h>
72 #include <stdarg.h>
73 #include <stdbool.h>
74 #include <stdint.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <syslog.h>
79 #include <unistd.h>
80 #if defined(_LIBC)
81 #include "extern.h"
82 #define ubsan_vsyslog vsyslog_ss
83 #define ASSERT(x) _DIAGASSERT(x)
84 #else
85 #define ubsan_vsyslog vsyslog_r
86 #define ASSERT(x) assert(x)
87 #endif
88 /* These macros are available in _KERNEL only */
89 #define SET(t, f)       ((t) |= (f))
90 #define ISSET(t, f)     ((t) & (f))
91 #define CLR(t, f)       ((t) &= ~(f))
92 #endif
93
94 #define REINTERPRET_CAST(__dt, __st)    ((__dt)(__st))
95 #define STATIC_CAST(__dt, __st)         ((__dt)(__st))
96
97 #define ACK_REPORTED    __BIT(31)
98
99 #define MUL_STRING      "*"
100 #define PLUS_STRING     "+"
101 #define MINUS_STRING    "-"
102 #define DIVREM_STRING   "divrem"
103
104 #define CFI_VCALL               0
105 #define CFI_NVCALL              1
106 #define CFI_DERIVEDCAST         2
107 #define CFI_UNRELATEDCAST       3
108 #define CFI_ICALL               4
109 #define CFI_NVMFCALL            5
110 #define CFI_VMFCALL             6
111
112 #define NUMBER_MAXLEN   128
113 #define LOCATION_MAXLEN (PATH_MAX + 32 /* ':LINE:COLUMN' */)
114
115 #define WIDTH_8         8
116 #define WIDTH_16        16
117 #define WIDTH_32        32
118 #define WIDTH_64        64
119 #define WIDTH_80        80
120 #define WIDTH_96        96
121 #define WIDTH_128       128
122
123 #define NUMBER_SIGNED_BIT       1U
124
125 #if __SIZEOF_INT128__
126 typedef __int128 longest;
127 typedef unsigned __int128 ulongest;
128 #else
129 typedef int64_t longest;
130 typedef uint64_t ulongest;
131 #endif
132
133 #ifndef _KERNEL
134 static int ubsan_flags = -1;
135 #define UBSAN_ABORT     __BIT(0)
136 #define UBSAN_STDOUT    __BIT(1)
137 #define UBSAN_STDERR    __BIT(2)
138 #define UBSAN_SYSLOG    __BIT(3)
139 #endif
140
141 /* Undefined Behavior specific defines and structures */
142
143 #define KIND_INTEGER    0
144 #define KIND_FLOAT      1
145 #define KIND_UNKNOWN    UINT16_MAX
146
147 struct CSourceLocation {
148         char *mFilename;
149         uint32_t mLine;
150         uint32_t mColumn;
151 };
152
153 struct CTypeDescriptor {
154         uint16_t mTypeKind;
155         uint16_t mTypeInfo;
156         uint8_t mTypeName[1];
157 };
158
159 struct COverflowData {
160         struct CSourceLocation mLocation;
161         struct CTypeDescriptor *mType;
162 };
163
164 struct CUnreachableData {
165         struct CSourceLocation mLocation;
166 };
167
168 struct CCFICheckFailData {
169         uint8_t mCheckKind;
170         struct CSourceLocation mLocation;
171         struct CTypeDescriptor *mType;
172 };
173
174 struct CDynamicTypeCacheMissData {
175         struct CSourceLocation mLocation;
176         struct CTypeDescriptor *mType;
177         void *mTypeInfo;
178         uint8_t mTypeCheckKind;
179 };
180
181 struct CFunctionTypeMismatchData {
182         struct CSourceLocation mLocation;
183         struct CTypeDescriptor *mType;
184 };
185
186 struct CInvalidBuiltinData {
187         struct CSourceLocation mLocation;
188         uint8_t mKind;
189 };
190
191 struct CInvalidValueData {
192         struct CSourceLocation mLocation;
193         struct CTypeDescriptor *mType;
194 };
195
196 struct CNonNullArgData {
197         struct CSourceLocation mLocation;
198         struct CSourceLocation mAttributeLocation;
199         int mArgIndex;
200 };
201
202 struct CNonNullReturnData {
203         struct CSourceLocation mAttributeLocation;
204 };
205
206 struct COutOfBoundsData {
207         struct CSourceLocation mLocation;
208         struct CTypeDescriptor *mArrayType;
209         struct CTypeDescriptor *mIndexType;
210 };
211
212 struct CPointerOverflowData {
213         struct CSourceLocation mLocation;
214 };
215
216 struct CShiftOutOfBoundsData {
217         struct CSourceLocation mLocation;
218         struct CTypeDescriptor *mLHSType;
219         struct CTypeDescriptor *mRHSType;
220 };
221
222 struct CTypeMismatchData {
223         struct CSourceLocation mLocation;
224         struct CTypeDescriptor *mType;
225         unsigned long mLogAlignment;
226         uint8_t mTypeCheckKind;
227 };
228
229 struct CTypeMismatchData_v1 {
230         struct CSourceLocation mLocation;
231         struct CTypeDescriptor *mType;
232         uint8_t mLogAlignment;
233         uint8_t mTypeCheckKind;
234 };
235
236 struct CVLABoundData {
237         struct CSourceLocation mLocation;
238         struct CTypeDescriptor *mType;
239 };
240
241 struct CFloatCastOverflowData {
242         struct CSourceLocation mLocation;       /* This field exists in this struct since 2015 August 11th */
243         struct CTypeDescriptor *mFromType;
244         struct CTypeDescriptor *mToType;
245 };
246
247 /* Local utility functions */
248 static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
249 static bool isAlreadyReported(struct CSourceLocation *pLocation);
250 static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
251 static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation);
252 #ifdef __SIZEOF_INT128__
253 static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128);
254 #endif
255 static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L);
256 static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L);
257 #ifndef _KERNEL
258 static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber);
259 static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
260 #endif
261 static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
262 static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
263 #ifndef _KERNEL
264 static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
265 #endif
266 static void DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
267 static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
268 static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
269 static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
270 static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
271 static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth);
272
273 /* Unused in this implementation, emitted by the C++ check dynamic type cast. */
274 intptr_t __ubsan_vptr_type_cache[128];
275
276 /* Public symbols used in the instrumentation of the code generation part */
277 void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
278 void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
279 void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
280 void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer);
281 void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
282 void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
283 void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
284 void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
285 void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
286 void __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
287 void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
288 void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
289 void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
290 void __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
291 void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
292 void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
293 void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulVal);
294 void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulVal);
295 void __ubsan_handle_missing_return(struct CUnreachableData *pData);
296 void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
297 void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
298 void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldVal);
299 void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldVal);
300 void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
301 void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
302 void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
303 void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
304 void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
305 void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
306 void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
307 void __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
308 void __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex);
309 void __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex);
310 void __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
311 void __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
312 void __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
313 void __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
314 void __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
315 void __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
316 void __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer);
317 void __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer);
318 void __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
319 void __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
320 void __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound);
321 void __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound);
322 void __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr);
323
324 static void HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation);
325 static void HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue);
326 static void HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData);
327 static void HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer);
328 static void HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound);
329 static void HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex);
330 static void HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
331 static void HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue);
332 static void HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData);
333 static void HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
334 static void HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer);
335 static void HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
336 static void HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom);
337 static void HandleMissingReturn(bool isFatal, struct CUnreachableData *pData);
338 static void HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData);
339 static void HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
340 static void HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
341
342 static void
343 HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
344 {
345         char szLocation[LOCATION_MAXLEN];
346         char szLHS[NUMBER_MAXLEN];
347         char szRHS[NUMBER_MAXLEN];
348
349         ASSERT(pData);
350
351         if (isAlreadyReported(&pData->mLocation))
352                 return;
353
354         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
355         DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mType, ulLHS);
356         DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mType, ulRHS);
357
358         Report(isFatal, "UBSan: Undefined Behavior in %s, %s integer overflow: %s %s %s cannot be represented in type %s\n",
359                szLocation, ISSET(pData->mType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", szLHS, szOperation, szRHS, pData->mType->mTypeName);
360 }
361
362 static void
363 HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
364 {
365         char szLocation[LOCATION_MAXLEN];
366         char szOldValue[NUMBER_MAXLEN];
367
368         ASSERT(pData);
369
370         if (isAlreadyReported(&pData->mLocation))
371                 return;
372
373         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
374         DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
375
376         Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
377                szLocation, szOldValue, pData->mType->mTypeName);
378 }
379
380 static void
381 HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
382 {
383         char szLocation[LOCATION_MAXLEN];
384
385         ASSERT(pData);
386
387         if (isAlreadyReported(&pData->mLocation))
388                 return;
389
390         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
391
392         Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
393                szLocation);
394 }
395
396 static void
397 HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
398 {
399         char szLocation[LOCATION_MAXLEN];
400
401         ASSERT(mLocation);
402         ASSERT(mType);
403
404         if (isAlreadyReported(mLocation))
405                 return;
406
407         DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
408
409         if (ulPointer == 0) {
410                 Report(isFatal, "UBSan: Undefined Behavior in %s, %s null pointer of type %s\n",
411                        szLocation, DeserializeTypeCheckKind(mTypeCheckKind), mType->mTypeName);
412         } else if ((mLogAlignment - 1) & ulPointer) {
413                 Report(isFatal, "UBSan: Undefined Behavior in %s, %s misaligned address %p for type %s which requires %ld byte alignment\n",
414                        szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName, mLogAlignment);
415         } else {
416                 Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %p with insufficient space for an object of type %s\n",
417                        szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName);
418         }
419 }
420
421 static void
422 HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
423 {
424         char szLocation[LOCATION_MAXLEN];
425         char szBound[NUMBER_MAXLEN];
426
427         ASSERT(pData);
428
429         if (isAlreadyReported(&pData->mLocation))
430                 return;
431
432         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
433         DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
434
435         Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
436                szLocation, szBound);
437 }
438
439 static void
440 HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
441 {
442         char szLocation[LOCATION_MAXLEN];
443         char szIndex[NUMBER_MAXLEN];
444
445         ASSERT(pData);
446
447         if (isAlreadyReported(&pData->mLocation))
448                 return;
449
450         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
451         DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
452
453         Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
454                szLocation, szIndex, pData->mArrayType->mTypeName);
455 }
456
457 static void
458 HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
459 {
460         char szLocation[LOCATION_MAXLEN];
461         char szLHS[NUMBER_MAXLEN];
462         char szRHS[NUMBER_MAXLEN];
463
464         ASSERT(pData);
465
466         if (isAlreadyReported(&pData->mLocation))
467                 return;
468
469         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
470         DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mLHSType, ulLHS);
471         DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mRHSType, ulRHS);
472
473         if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
474                 Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
475                        szLocation, szRHS);
476         else if (isShiftExponentTooLarge(szLocation, pData->mRHSType, ulRHS, zDeserializeTypeWidth(pData->mLHSType)))
477                 Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is too large for %zu-bit type %s\n",
478                        szLocation, szRHS, zDeserializeTypeWidth(pData->mLHSType), pData->mLHSType->mTypeName);
479         else if (isNegativeNumber(szLocation, pData->mLHSType, ulLHS))
480                 Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of negative value %s\n",
481                        szLocation, szLHS);
482         else
483                 Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of %s by %s places cannot be represented in type %s\n",
484                        szLocation, szLHS, szRHS, pData->mLHSType->mTypeName);
485 }
486
487 static void
488 HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
489 {
490         char szLocation[LOCATION_MAXLEN];
491         char szValue[NUMBER_MAXLEN];
492
493         ASSERT(pData);
494
495         if (isAlreadyReported(&pData->mLocation))
496                 return;
497
498         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
499         DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
500
501         Report(isFatal, "UBSan: Undefined Behavior in %s, load of value %s is not a valid value for type %s\n",
502                szLocation, szValue, pData->mType->mTypeName);
503 }
504
505 static void
506 HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
507 {
508         char szLocation[LOCATION_MAXLEN];
509
510         ASSERT(pData);
511
512         if (isAlreadyReported(&pData->mLocation))
513                 return;
514
515         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
516
517         Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
518                szLocation, DeserializeBuiltinCheckKind(pData->mKind));
519 }
520
521 static void
522 HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
523 {
524         char szLocation[LOCATION_MAXLEN];
525
526         /*
527          * There is no a portable C solution to translate an address of a
528          * function to its name. On the cost of getting this routine simple
529          * and portable without ifdefs between the userland and the kernel
530          * just print the address of the function as-is.
531          *
532          * For better diagnostic messages in the userland, users shall use
533          * the full upstream version shipped along with the compiler toolchain.
534          */
535
536         ASSERT(pData);
537
538         if (isAlreadyReported(&pData->mLocation))
539                 return;
540
541         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
542
543         Report(isFatal, "UBSan: Undefined Behavior in %s, call to function %#lx through pointer to incorrect function type %s\n",
544               szLocation, ulFunction, pData->mType->mTypeName);
545 }
546
547 static void
548 HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
549 {
550         char szLocation[LOCATION_MAXLEN];
551
552         /*
553          * This is a minimal implementation without diving into C++
554          * specifics and (Itanium) ABI deserialization.
555          */
556
557         ASSERT(pData);
558
559         if (isAlreadyReported(&pData->mLocation))
560                 return;
561
562         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
563
564         if (pData->mCheckKind == CFI_ICALL || pData->mCheckKind == CFI_VMFCALL) {
565                 Report(isFatal, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx)\n",
566                       szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable);
567         } else {
568                 Report(isFatal || FromUnrecoverableHandler, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx; %s vtable; from %s handler; Program Counter %#lx; Frame Pointer %#lx)\n",
569                       szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable, *bValidVtable ? "valid" : "invalid", *FromUnrecoverableHandler ? "unrecoverable" : "recoverable", *ProgramCounter, *FramePointer);
570         }
571 }
572
573 static void
574 HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
575 {
576 #if 0
577         char szLocation[LOCATION_MAXLEN];
578
579         /*
580          * Unimplemented.
581          *
582          * This UBSan handler is special as the check has to be impelemented
583          * in an implementation. In order to handle it there is need to
584          * introspect into C++ ABI internals (RTTI) and use low-level
585          * C++ runtime interfaces.
586          */
587
588         ASSERT(pData);
589
590         if (isAlreadyReported(&pData->mLocation))
591                 return;
592
593         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
594
595         Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %#lx which might not point to an object of type %s\n"
596               szLocation, DeserializeTypeCheckKind(pData->mTypeCheckKind), ulPointer, pData->mType);
597 #endif
598 }
599
600 static void
601 HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
602 {
603         char szLocation[LOCATION_MAXLEN];
604         char szFrom[NUMBER_MAXLEN];
605
606         ASSERT(pData);
607
608         if (isAlreadyReported(&pData->mLocation))
609                 return;
610
611         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
612         DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
613
614         Report(isFatal, "UBSan: Undefined Behavior in %s, %s (of type %s) is outside the range of representable values of type %s\n",
615                szLocation, szFrom, pData->mFromType->mTypeName, pData->mToType->mTypeName);
616 }
617
618 static void
619 HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
620 {
621         char szLocation[LOCATION_MAXLEN];
622
623         ASSERT(pData);
624
625         if (isAlreadyReported(&pData->mLocation))
626                 return;
627
628         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
629
630         Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
631                szLocation);
632 }
633
634 static void
635 HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
636 {
637         char szLocation[LOCATION_MAXLEN];
638         char szAttributeLocation[LOCATION_MAXLEN];
639
640         ASSERT(pData);
641
642         if (isAlreadyReported(&pData->mLocation))
643                 return;
644
645         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
646         if (pData->mAttributeLocation.mFilename)
647                 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
648         else
649                 szAttributeLocation[0] = '\0';
650
651         Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer passed as argument %d, which is declared to never be null%s%s\n",
652                szLocation, pData->mArgIndex, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
653 }
654
655 static void
656 HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
657 {
658         char szLocation[LOCATION_MAXLEN];
659         char szAttributeLocation[LOCATION_MAXLEN];
660
661         ASSERT(pData);
662         ASSERT(pLocationPointer);
663
664         if (isAlreadyReported(pLocationPointer))
665                 return;
666
667         DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
668         if (pData->mAttributeLocation.mFilename)
669                 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
670         else
671                 szAttributeLocation[0] = '\0';
672
673         Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer returned from function declared to never return null%s%s\n",
674                szLocation, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
675 }
676
677 static void
678 HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
679 {
680         char szLocation[LOCATION_MAXLEN];
681
682         ASSERT(pData);
683
684         if (isAlreadyReported(&pData->mLocation))
685                 return;
686
687         DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
688
689         Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
690                szLocation, ulBase, ulResult);
691 }
692
693 /* Definions of public symbols emitted by the instrumentation code */
694 void
695 __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
696 {
697
698         ASSERT(pData);
699
700         HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
701 }
702
703 void
704 __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
705 {
706
707         ASSERT(pData);
708
709         HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
710 }
711
712 void
713 __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
714 {
715
716         ASSERT(pData);
717
718         HandleBuiltinUnreachable(true, pData);
719 }
720
721 void
722 __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
723 {
724
725         ASSERT(pData);
726
727         HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
728 }
729
730 void
731 __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
732 {
733
734         ASSERT(pData);
735
736         HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
737 }
738
739 void
740 __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
741 {
742
743         ASSERT(pData);
744
745         HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
746 }
747
748 void
749 __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
750 {
751
752         ASSERT(pData);
753
754         HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
755 }
756
757 void
758 __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
759 {
760
761         ASSERT(pData);
762
763         HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
764 }
765
766 void
767 __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
768 {
769
770         ASSERT(pData);
771
772         HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
773 }
774
775 void
776 __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
777 {
778
779         ASSERT(pData);
780
781         HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
782 }
783
784 void
785 __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
786 {
787
788         ASSERT(pData);
789
790         HandleFloatCastOverflow(false, pData, ulFrom);
791 }
792
793 void
794 __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
795 {
796
797         ASSERT(pData);
798
799         HandleFloatCastOverflow(true, pData, ulFrom);
800 }
801
802 void
803 __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
804 {
805
806         ASSERT(pData);
807
808         HandleFunctionTypeMismatch(false, pData, ulFunction);
809 }
810
811 void
812 __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
813 {
814
815         ASSERT(pData);
816
817         HandleFunctionTypeMismatch(false, pData, ulFunction);
818 }
819
820 void
821 __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
822 {
823
824         ASSERT(pData);
825
826         HandleInvalidBuiltin(true, pData);
827 }
828
829 void
830 __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
831 {
832
833         ASSERT(pData);
834
835         HandleInvalidBuiltin(true, pData);
836 }
837
838 void
839 __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
840 {
841
842         ASSERT(pData);
843
844         HandleLoadInvalidValue(false, pData, ulValue);
845 }
846
847 void
848 __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
849 {
850
851         ASSERT(pData);
852
853         HandleLoadInvalidValue(true, pData, ulValue);
854 }
855
856 void
857 __ubsan_handle_missing_return(struct CUnreachableData *pData)
858 {
859
860         ASSERT(pData);
861
862         HandleMissingReturn(true, pData);
863 }
864
865 void
866 __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
867 {
868
869         ASSERT(pData);
870
871         HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
872 }
873
874 void
875 __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
876 {
877
878         ASSERT(pData);
879
880         HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
881 }
882
883 void
884 __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
885 {
886
887         ASSERT(pData);
888
889         HandleNegateOverflow(false, pData, ulOldValue);
890 }
891
892 void
893 __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
894 {
895
896         ASSERT(pData);
897
898         HandleNegateOverflow(true, pData, ulOldValue);
899 }
900
901 void
902 __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
903 {
904
905         ASSERT(pData);
906
907         HandleNonnullArg(false, pData);
908 }
909
910 void
911 __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
912 {
913
914         ASSERT(pData);
915
916         HandleNonnullArg(true, pData);
917 }
918
919 void
920 __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
921 {
922
923         ASSERT(pData);
924         ASSERT(pLocationPointer);
925
926         HandleNonnullReturn(false, pData, pLocationPointer);
927 }
928
929 void
930 __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
931 {
932
933         ASSERT(pData);
934         ASSERT(pLocationPointer);
935
936         HandleNonnullReturn(true, pData, pLocationPointer);
937 }
938
939 void
940 __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
941 {
942
943         ASSERT(pData);
944
945         HandleNonnullArg(false, pData);
946 }
947
948 void
949 __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
950 {
951
952         ASSERT(pData);
953
954         HandleNonnullArg(true, pData);
955 }
956
957 void
958 __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
959 {
960
961         ASSERT(pData);
962         ASSERT(pLocationPointer);
963
964         HandleNonnullReturn(false, pData, pLocationPointer);
965 }
966
967 void
968 __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
969 {
970
971         ASSERT(pData);
972         ASSERT(pLocationPointer);
973
974         HandleNonnullReturn(true, pData, pLocationPointer);
975 }
976
977 void
978 __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
979 {
980
981         ASSERT(pData);
982
983         HandleOutOfBounds(false, pData, ulIndex);
984 }
985
986 void
987 __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
988 {
989
990         ASSERT(pData);
991
992         HandleOutOfBounds(true, pData, ulIndex);
993 }
994
995 void
996 __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
997 {
998
999         ASSERT(pData);
1000
1001         HandlePointerOverflow(false, pData, ulBase, ulResult);
1002 }
1003
1004 void
1005 __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1006 {
1007
1008         ASSERT(pData);
1009
1010         HandlePointerOverflow(true, pData, ulBase, ulResult);
1011 }
1012
1013 void
1014 __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1015 {
1016
1017         ASSERT(pData);
1018
1019         HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
1020 }
1021
1022 void
1023 __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1024 {
1025
1026         ASSERT(pData);
1027
1028         HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
1029 }
1030
1031 void
1032 __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1033 {
1034
1035         ASSERT(pData);
1036
1037         HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
1038 }
1039
1040 void
1041 __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1042 {
1043
1044         ASSERT(pData);
1045
1046         HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
1047 }
1048
1049 void
1050 __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
1051 {
1052
1053         ASSERT(pData);
1054
1055         HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1056 }
1057
1058 void
1059 __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
1060 {
1061
1062         ASSERT(pData);
1063
1064         HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1065 }
1066
1067 void
1068 __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1069 {
1070
1071         ASSERT(pData);
1072
1073         HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1074 }
1075
1076 void
1077 __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1078 {
1079
1080         ASSERT(pData);
1081
1082         HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1083 }
1084
1085 void
1086 __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
1087 {
1088
1089         ASSERT(pData);
1090
1091         HandleVlaBoundNotPositive(false, pData, ulBound);
1092 }
1093
1094 void
1095 __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
1096 {
1097
1098         ASSERT(pData);
1099
1100         HandleVlaBoundNotPositive(true, pData, ulBound);
1101 }
1102
1103 void
1104 __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
1105 {
1106         /*
1107          * Unimplemented.
1108          *
1109          * The __ubsan_on_report() feature is non trivial to implement in a
1110          * shared code between the kernel and userland. It's also opening
1111          * new sets of potential problems as we are not expected to slow down
1112          * execution of certain kernel subsystems (synchronization issues,
1113          * interrupt handling etc).
1114          *
1115          * A proper solution would need probably a lock-free bounded queue built
1116          * with atomic operations with the property of miltiple consumers and
1117          * multiple producers. Maintaining and validating such code is not
1118          * worth the effort.
1119          *
1120          * A legitimate user - besides testing framework - is a debugger plugin
1121          * intercepting reports from the UBSan instrumentation. For such
1122          * scenarios it is better to run the Clang/GCC version.
1123          */
1124 }
1125
1126 /* Local utility functions */
1127
1128 static void
1129 Report(bool isFatal, const char *pFormat, ...)
1130 {
1131         va_list ap;
1132
1133         ASSERT(pFormat);
1134
1135         va_start(ap, pFormat);
1136 #if defined(_KERNEL)
1137         if (isFatal)
1138                 vpanic(pFormat, ap);
1139         else
1140                 vprintf(pFormat, ap);
1141 #else
1142         if (ubsan_flags == -1) {
1143                 char buf[1024];
1144                 char *p;
1145
1146                 ubsan_flags = UBSAN_STDERR;
1147
1148                 if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
1149                         for (p = buf; *p; p++) {
1150                                 switch (*p) {
1151                                 case 'a':
1152                                         SET(ubsan_flags, UBSAN_ABORT);
1153                                         break;
1154                                 case 'A':
1155                                         CLR(ubsan_flags, UBSAN_ABORT);
1156                                         break;
1157                                 case 'e':
1158                                         SET(ubsan_flags, UBSAN_STDERR);
1159                                         break;
1160                                 case 'E':
1161                                         CLR(ubsan_flags, UBSAN_STDERR);
1162                                         break;
1163                                 case 'l':
1164                                         SET(ubsan_flags, UBSAN_SYSLOG);
1165                                         break;
1166                                 case 'L':
1167                                         CLR(ubsan_flags, UBSAN_SYSLOG);
1168                                         break;
1169                                 case 'o':
1170                                         SET(ubsan_flags, UBSAN_STDOUT);
1171                                         break;
1172                                 case 'O':
1173                                         CLR(ubsan_flags, UBSAN_STDOUT);
1174                                         break;
1175                                 default:
1176                                         break;
1177                                 }
1178                         }
1179                 }
1180         }
1181
1182         // The *v*print* functions can flush the va_list argument.
1183         // Create a local copy for each call to prevent invalid read.
1184         if (ISSET(ubsan_flags, UBSAN_STDOUT)) {
1185                 va_list tmp;
1186                 va_copy(tmp, ap);
1187                 vprintf(pFormat, tmp);
1188                 va_end(tmp);
1189                 fflush(stdout);
1190         }
1191         if (ISSET(ubsan_flags, UBSAN_STDERR)) {
1192                 va_list tmp;
1193                 va_copy(tmp, ap);
1194                 vfprintf(stderr, pFormat, tmp);
1195                 va_end(tmp);
1196                 fflush(stderr);
1197         }
1198         if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
1199                 va_list tmp;
1200                 va_copy(tmp, ap);
1201                 struct syslog_data SyslogData = SYSLOG_DATA_INIT;
1202                 ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
1203                 va_end(tmp);
1204         }
1205         if (isFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
1206                 abort();
1207                 /* NOTREACHED */
1208         }
1209 #endif
1210         va_end(ap);
1211 }
1212
1213 static bool
1214 isAlreadyReported(struct CSourceLocation *pLocation)
1215 {
1216         /*
1217          * This code is shared between libc, kernel and standalone usage.
1218          * It shall work in early bootstrap phase of both of them.
1219          */
1220
1221         uint32_t siOldValue;
1222         volatile uint32_t *pLine;
1223
1224         ASSERT(pLocation);
1225
1226         pLine = &pLocation->mLine;
1227
1228         do {
1229                 siOldValue = *pLine;
1230         } while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
1231
1232         return ISSET(siOldValue, ACK_REPORTED);
1233 }
1234
1235 static size_t
1236 zDeserializeTypeWidth(struct CTypeDescriptor *pType)
1237 {
1238         size_t zWidth = 0;
1239
1240         ASSERT(pType);
1241
1242         switch (pType->mTypeKind) {
1243         case KIND_INTEGER:
1244                 zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
1245                 break;
1246         case KIND_FLOAT:
1247                 zWidth = pType->mTypeInfo;
1248                 break;
1249         default:
1250                 Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
1251                 /* NOTREACHED */
1252         }
1253
1254         /* Invalid width will be transformed to 0 */
1255         ASSERT(zWidth > 0);
1256
1257         return zWidth;
1258 }
1259
1260 static void
1261 DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
1262 {
1263
1264         ASSERT(pLocation);
1265         ASSERT(pLocation->mFilename);
1266
1267         snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
1268 }
1269
1270 #ifdef __SIZEOF_INT128__
1271 static void
1272 DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
1273 {
1274         char szBuf[3]; /* 'XX\0' */
1275         char rgNumber[sizeof(ulongest)];
1276         ssize_t zI;
1277
1278         memcpy(rgNumber, &U128, sizeof(U128));
1279
1280         strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
1281 #if BYTE_ORDER == LITTLE_ENDIAN
1282         for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
1283 #else
1284         for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
1285 #endif
1286                 snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
1287                 strlcat(pBuffer, szBuf, zBUfferLength);
1288         }
1289         strlcat(pBuffer, ")", zBUfferLength);
1290 }
1291 #endif
1292
1293 static void
1294 DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
1295 {
1296
1297         ASSERT(pBuffer);
1298         ASSERT(zBUfferLength > 0);
1299         ASSERT(pType);
1300         ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1301
1302         switch (zDeserializeTypeWidth(pType)) {
1303         default:
1304                 ASSERT(0 && "Invalid codepath");
1305                 /* NOTREACHED */
1306 #ifdef __SIZEOF_INT128__
1307         case WIDTH_128:
1308                 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1309                 break;
1310 #endif
1311         case WIDTH_64:
1312         case WIDTH_32:
1313         case WIDTH_16:
1314         case WIDTH_8:
1315                 snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
1316                 break;
1317         }
1318 }
1319
1320 static void
1321 DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
1322 {
1323
1324         ASSERT(pBuffer);
1325         ASSERT(zBUfferLength > 0);
1326         ASSERT(pType);
1327         ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1328
1329         switch (zDeserializeTypeWidth(pType)) {
1330         default:
1331                 ASSERT(0 && "Invalid codepath");
1332                 /* NOTREACHED */
1333 #ifdef __SIZEOF_INT128__
1334         case WIDTH_128:
1335                 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1336                 break;
1337 #endif
1338         case WIDTH_64:
1339         case WIDTH_32:
1340         case WIDTH_16:
1341         case WIDTH_8:
1342                 snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
1343                 break;
1344         }
1345 }
1346
1347 #ifndef _KERNEL
1348 static void
1349 DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
1350 {
1351         double D;
1352 #ifdef __HAVE_LONG_DOUBLE
1353         long double LD;
1354 #endif
1355
1356         ASSERT(pBuffer);
1357         ASSERT(zBUfferLength > 0);
1358         ASSERT(pType);
1359         ASSERT(pNumber);
1360         /*
1361          * This function handles 64-bit number over a pointer on 32-bit CPUs.
1362          */
1363         ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
1364         ASSERT(sizeof(D) == sizeof(uint64_t));
1365 #ifdef __HAVE_LONG_DOUBLE
1366         ASSERT(sizeof(LD) > sizeof(uint64_t));
1367 #endif
1368
1369         switch (zDeserializeTypeWidth(pType)) {
1370 #ifdef __HAVE_LONG_DOUBLE
1371         case WIDTH_128:
1372         case WIDTH_96:
1373         case WIDTH_80:
1374                 memcpy(&LD, pNumber, sizeof(long double));
1375                 snprintf(pBuffer, zBUfferLength, "%Lg", LD);
1376                 break;
1377 #endif
1378         case WIDTH_64:
1379                 memcpy(&D, pNumber, sizeof(double));
1380                 snprintf(pBuffer, zBUfferLength, "%g", D);
1381                 break;
1382         }
1383 }
1384
1385 static void
1386 DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1387 {
1388         float F;
1389         double D;
1390         uint32_t U32;
1391
1392         ASSERT(pBuffer);
1393         ASSERT(zBUfferLength > 0);
1394         ASSERT(pType);
1395         ASSERT(sizeof(F) == sizeof(uint32_t));
1396         ASSERT(sizeof(D) == sizeof(uint64_t));
1397
1398         switch (zDeserializeTypeWidth(pType)) {
1399         case WIDTH_64:
1400                 memcpy(&D, &ulNumber, sizeof(double));
1401                 snprintf(pBuffer, zBUfferLength, "%g", D);
1402                 break;
1403         case WIDTH_32:
1404                 /*
1405                  * On supported platforms sizeof(float)==sizeof(uint32_t)
1406                  * unsigned long is either 32 or 64-bit, cast it to 32-bit
1407                  * value in order to call memcpy(3) in an Endian-aware way.
1408                  */
1409                 U32 = STATIC_CAST(uint32_t, ulNumber);
1410                 memcpy(&F, &U32, sizeof(float));
1411                 snprintf(pBuffer, zBUfferLength, "%g", F);
1412                 break;
1413         case WIDTH_16:
1414                 snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
1415                 break;
1416         }
1417 }
1418 #endif
1419
1420 static longest
1421 llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1422 {
1423         size_t zNumberWidth;
1424         longest L = 0;
1425
1426         ASSERT(szLocation);
1427         ASSERT(pType);
1428
1429         zNumberWidth = zDeserializeTypeWidth(pType);
1430         switch (zNumberWidth) {
1431         default:
1432                 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1433                 /* NOTREACHED */
1434         case WIDTH_128:
1435 #ifdef __SIZEOF_INT128__
1436                 memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
1437 #else
1438                 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1439                 /* NOTREACHED */
1440 #endif
1441                 break;
1442         case WIDTH_64:
1443                 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1444                         L = *REINTERPRET_CAST(int64_t *, ulNumber);
1445                 } else {
1446                         L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
1447                 }
1448                 break;
1449         case WIDTH_32:
1450                 L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
1451                 break;
1452         case WIDTH_16:
1453                 L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
1454                 break;
1455         case WIDTH_8:
1456                 L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
1457                 break;
1458         }
1459
1460         return L;
1461 }
1462
1463 static ulongest
1464 llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1465 {
1466         size_t zNumberWidth;
1467         ulongest UL = 0;
1468
1469         ASSERT(pType);
1470
1471         zNumberWidth = zDeserializeTypeWidth(pType);
1472         switch (zNumberWidth) {
1473         default:
1474                 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1475                 /* NOTREACHED */
1476         case WIDTH_128:
1477 #ifdef __SIZEOF_INT128__
1478                 memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
1479                 break;
1480 #else
1481                 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1482                 /* NOTREACHED */
1483 #endif
1484         case WIDTH_64:
1485                 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1486                         UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
1487                         break;
1488                 }
1489                 /* FALLTHROUGH */
1490         case WIDTH_32:
1491                 /* FALLTHROUGH */
1492         case WIDTH_16:
1493                 /* FALLTHROUGH */
1494         case WIDTH_8:
1495                 UL = ulNumber;
1496                 break;
1497         }
1498
1499         return UL;
1500 }
1501
1502 #ifndef _KERNEL
1503 static void
1504 DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1505 {
1506         size_t zNumberWidth;
1507
1508         ASSERT(szLocation);
1509         ASSERT(pBuffer);
1510         ASSERT(zBUfferLength > 0);
1511         ASSERT(pType);
1512         ASSERT(pType->mTypeKind == KIND_FLOAT);
1513
1514         zNumberWidth = zDeserializeTypeWidth(pType);
1515         switch (zNumberWidth) {
1516         default:
1517                 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1518                 /* NOTREACHED */
1519 #ifdef __HAVE_LONG_DOUBLE
1520         case WIDTH_128:
1521         case WIDTH_96:
1522         case WIDTH_80:
1523                 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1524                 break;
1525 #endif
1526         case WIDTH_64:
1527                 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1528                         DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1529                         break;
1530                 }
1531         case WIDTH_32:
1532         case WIDTH_16:
1533                 DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
1534                 break;
1535         }
1536 }
1537 #endif
1538
1539 static void
1540 DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1541 {
1542
1543         ASSERT(szLocation);
1544         ASSERT(pBuffer);
1545         ASSERT(zBUfferLength > 0);
1546         ASSERT(pType);
1547
1548         switch(pType->mTypeKind) {
1549         case KIND_INTEGER:
1550                 if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
1551                         longest L = llliGetNumber(szLocation, pType, ulNumber);
1552                         DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
1553                 } else {
1554                         ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
1555                         DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
1556                 }
1557                 break;
1558         case KIND_FLOAT:
1559 #ifdef _KERNEL
1560                 Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
1561                 /* NOTREACHED */
1562 #else
1563                 DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
1564 #endif
1565                 break;
1566         case KIND_UNKNOWN:
1567                 Report(true, "UBSan: Unknown Type in %s\n", szLocation);
1568                 /* NOTREACHED */
1569                 break;
1570         }
1571 }
1572
1573 static const char *
1574 DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
1575 {
1576         const char *rgczTypeCheckKinds[] = {
1577                 "load of",
1578                 "store to",
1579                 "reference binding to",
1580                 "member access within",
1581                 "member call on",
1582                 "constructor call on",
1583                 "downcast of",
1584                 "downcast of",
1585                 "upcast of",
1586                 "cast to virtual base of",
1587                 "_Nonnull binding to",
1588                 "dynamic operation on"
1589         };
1590
1591         ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
1592
1593         return rgczTypeCheckKinds[hhuTypeCheckKind];
1594 }
1595
1596 static const char *
1597 DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
1598 {
1599         const char *rgczBuiltinCheckKinds[] = {
1600                 "ctz()",
1601                 "clz()"
1602         };
1603
1604         ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
1605
1606         return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
1607 }
1608
1609 static const char *
1610 DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
1611 {
1612         const char *rgczCFICheckKinds[] = {
1613                 "virtual call",                                 // CFI_VCALL
1614                 "non-virtual call",                             // CFI_NVCALL
1615                 "base-to-derived cast",                         // CFI_DERIVEDCAST
1616                 "cast to unrelated type",                       // CFI_UNRELATEDCAST
1617                 "indirect function call",                       // CFI_ICALL
1618                 "non-virtual pointer to member function call",  // CFI_NVMFCALL
1619                 "virtual pointer to member function call",      // CFI_VMFCALL
1620         };
1621
1622         ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
1623
1624         return rgczCFICheckKinds[hhuCFICheckKind];
1625 }
1626
1627 static bool
1628 isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1629 {
1630
1631         ASSERT(szLocation);
1632         ASSERT(pType);
1633         ASSERT(pType->mTypeKind == KIND_INTEGER);
1634
1635         if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
1636                 return false;
1637
1638         return llliGetNumber(szLocation, pType, ulNumber) < 0;
1639 }
1640
1641 static bool
1642 isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
1643 {
1644
1645         ASSERT(szLocation);
1646         ASSERT(pType);
1647         ASSERT(pType->mTypeKind == KIND_INTEGER);
1648
1649         return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
1650 }