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