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
HandleOverflow(bool isFatal,struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS,const char * szOperation)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
HandleNegateOverflow(bool isFatal,struct COverflowData * pData,unsigned long ulOldValue)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
HandleBuiltinUnreachable(bool isFatal,struct CUnreachableData * pData)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
HandleTypeMismatch(bool isFatal,struct CSourceLocation * mLocation,struct CTypeDescriptor * mType,unsigned long mLogAlignment,uint8_t mTypeCheckKind,unsigned long ulPointer)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
HandleVlaBoundNotPositive(bool isFatal,struct CVLABoundData * pData,unsigned long ulBound)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
HandleOutOfBounds(bool isFatal,struct COutOfBoundsData * pData,unsigned long ulIndex)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
HandleShiftOutOfBounds(bool isFatal,struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)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
HandleLoadInvalidValue(bool isFatal,struct CInvalidValueData * pData,unsigned long ulValue)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
HandleInvalidBuiltin(bool isFatal,struct CInvalidBuiltinData * pData)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
HandleFunctionTypeMismatch(bool isFatal,struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)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
HandleCFIBadType(bool isFatal,struct CCFICheckFailData * pData,unsigned long ulVtable,bool * bValidVtable,bool * FromUnrecoverableHandler,unsigned long * ProgramCounter,unsigned long * FramePointer)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
HandleDynamicTypeCacheMiss(bool isFatal,struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)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
HandleFloatCastOverflow(bool isFatal,struct CFloatCastOverflowData * pData,unsigned long ulFrom)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
HandleMissingReturn(bool isFatal,struct CUnreachableData * pData)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
HandleNonnullArg(bool isFatal,struct CNonNullArgData * pData)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
HandleNonnullReturn(bool isFatal,struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)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
HandlePointerOverflow(bool isFatal,struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)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
HandleAlignmentAssumption(bool isFatal,struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)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
__ubsan_handle_add_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_add_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)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
__ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)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
__ubsan_handle_builtin_unreachable(struct CUnreachableData * pData)766 __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
767 {
768
769 ASSERT(pData);
770
771 HandleBuiltinUnreachable(true, pData);
772 }
773
774 void
__ubsan_handle_cfi_bad_type(struct CCFICheckFailData * pData,unsigned long ulVtable,bool bValidVtable,bool FromUnrecoverableHandler,unsigned long ProgramCounter,unsigned long FramePointer)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
__ubsan_handle_cfi_check_fail(struct CCFICheckFailData * pData,unsigned long ulValue,unsigned long ulValidVtable)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
__ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData * pData,unsigned long ulValue,unsigned long ulValidVtable)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
__ubsan_handle_divrem_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_divrem_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)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
__ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)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
__ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData * pData,unsigned long ulFrom)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
__ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData * pData,unsigned long ulFrom)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
__ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)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
__ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)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
__ubsan_handle_invalid_builtin(struct CInvalidBuiltinData * pData)874 __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
875 {
876
877 ASSERT(pData);
878
879 HandleInvalidBuiltin(true, pData);
880 }
881
882 void
__ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData * pData)883 __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
884 {
885
886 ASSERT(pData);
887
888 HandleInvalidBuiltin(true, pData);
889 }
890
891 void
__ubsan_handle_load_invalid_value(struct CInvalidValueData * pData,unsigned long ulValue)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
__ubsan_handle_load_invalid_value_abort(struct CInvalidValueData * pData,unsigned long ulValue)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
__ubsan_handle_missing_return(struct CUnreachableData * pData)910 __ubsan_handle_missing_return(struct CUnreachableData *pData)
911 {
912
913 ASSERT(pData);
914
915 HandleMissingReturn(true, pData);
916 }
917
918 void
__ubsan_handle_mul_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_mul_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_negate_overflow(struct COverflowData * pData,unsigned long ulOldValue)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
__ubsan_handle_negate_overflow_abort(struct COverflowData * pData,unsigned long ulOldValue)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
__ubsan_handle_nonnull_arg(struct CNonNullArgData * pData)955 __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
956 {
957
958 ASSERT(pData);
959
960 HandleNonnullArg(false, pData);
961 }
962
963 void
__ubsan_handle_nonnull_arg_abort(struct CNonNullArgData * pData)964 __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
965 {
966
967 ASSERT(pData);
968
969 HandleNonnullArg(true, pData);
970 }
971
972 void
__ubsan_handle_nonnull_return_v1(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)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
__ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)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
__ubsan_handle_nullability_arg(struct CNonNullArgData * pData)993 __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
994 {
995
996 ASSERT(pData);
997
998 HandleNonnullArg(false, pData);
999 }
1000
1001 void
__ubsan_handle_nullability_arg_abort(struct CNonNullArgData * pData)1002 __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
1003 {
1004
1005 ASSERT(pData);
1006
1007 HandleNonnullArg(true, pData);
1008 }
1009
1010 void
__ubsan_handle_nullability_return_v1(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)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
__ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)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
__ubsan_handle_out_of_bounds(struct COutOfBoundsData * pData,unsigned long ulIndex)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
__ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData * pData,unsigned long ulIndex)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
__ubsan_handle_pointer_overflow(struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)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
__ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)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
__ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_sub_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_sub_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)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
__ubsan_handle_type_mismatch(struct CTypeMismatchData * pData,unsigned long ulPointer)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
__ubsan_handle_type_mismatch_abort(struct CTypeMismatchData * pData,unsigned long ulPointer)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
__ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 * pData,unsigned long ulPointer)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
__ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 * pData,unsigned long ulPointer)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
__ubsan_handle_vla_bound_not_positive(struct CVLABoundData * pData,unsigned long ulBound)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
__ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData * pData,unsigned long ulBound)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
__ubsan_get_current_report_data(const char ** ppOutIssueKind,const char ** ppOutMessage,const char ** ppOutFilename,uint32_t * pOutLine,uint32_t * pOutCol,char ** ppOutMemoryAddr)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
Report(bool isFatal,const char * pFormat,...)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
isAlreadyReported(struct CSourceLocation * pLocation)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
zDeserializeTypeWidth(struct CTypeDescriptor * pType)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
DeserializeLocation(char * pBuffer,size_t zBUfferLength,struct CSourceLocation * pLocation)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
DeserializeUINT128(char * pBuffer,size_t zBUfferLength,struct CTypeDescriptor * pType,__uint128_t U128)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 }
1704