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