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