1 /* $NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $ */
4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
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
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.
39 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
44 __KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
46 __RCSID("$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
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))
65 #include "namespace.h"
67 #include <sys/param.h>
82 #define ubsan_vsyslog vsyslog_ss
83 #define ASSERT(x) _DIAGASSERT(x)
85 #define ubsan_vsyslog vsyslog_r
86 #define ASSERT(x) assert(x)
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))
94 #define REINTERPRET_CAST(__dt, __st) ((__dt)(__st))
95 #define STATIC_CAST(__dt, __st) ((__dt)(__st))
97 #define ACK_REPORTED __BIT(31)
99 #define MUL_STRING "*"
100 #define PLUS_STRING "+"
101 #define MINUS_STRING "-"
102 #define DIVREM_STRING "divrem"
106 #define CFI_DERIVEDCAST 2
107 #define CFI_UNRELATEDCAST 3
109 #define CFI_NVMFCALL 5
110 #define CFI_VMFCALL 6
112 #define NUMBER_MAXLEN 128
113 #define LOCATION_MAXLEN (PATH_MAX + 32 /* ':LINE:COLUMN' */)
121 #define WIDTH_128 128
123 #define NUMBER_SIGNED_BIT 1U
125 #if __SIZEOF_INT128__
126 typedef __int128 longest;
127 typedef unsigned __int128 ulongest;
129 typedef int64_t longest;
130 typedef uint64_t ulongest;
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)
141 /* Undefined Behavior specific defines and structures */
143 #define KIND_INTEGER 0
145 #define KIND_UNKNOWN UINT16_MAX
147 struct CSourceLocation {
153 struct CTypeDescriptor {
156 uint8_t mTypeName[1];
159 struct COverflowData {
160 struct CSourceLocation mLocation;
161 struct CTypeDescriptor *mType;
164 struct CUnreachableData {
165 struct CSourceLocation mLocation;
168 struct CCFICheckFailData {
170 struct CSourceLocation mLocation;
171 struct CTypeDescriptor *mType;
174 struct CDynamicTypeCacheMissData {
175 struct CSourceLocation mLocation;
176 struct CTypeDescriptor *mType;
178 uint8_t mTypeCheckKind;
181 struct CFunctionTypeMismatchData {
182 struct CSourceLocation mLocation;
183 struct CTypeDescriptor *mType;
186 struct CInvalidBuiltinData {
187 struct CSourceLocation mLocation;
191 struct CInvalidValueData {
192 struct CSourceLocation mLocation;
193 struct CTypeDescriptor *mType;
196 struct CNonNullArgData {
197 struct CSourceLocation mLocation;
198 struct CSourceLocation mAttributeLocation;
202 struct CNonNullReturnData {
203 struct CSourceLocation mAttributeLocation;
206 struct COutOfBoundsData {
207 struct CSourceLocation mLocation;
208 struct CTypeDescriptor *mArrayType;
209 struct CTypeDescriptor *mIndexType;
212 struct CPointerOverflowData {
213 struct CSourceLocation mLocation;
216 struct CShiftOutOfBoundsData {
217 struct CSourceLocation mLocation;
218 struct CTypeDescriptor *mLHSType;
219 struct CTypeDescriptor *mRHSType;
222 struct CTypeMismatchData {
223 struct CSourceLocation mLocation;
224 struct CTypeDescriptor *mType;
225 unsigned long mLogAlignment;
226 uint8_t mTypeCheckKind;
229 struct CTypeMismatchData_v1 {
230 struct CSourceLocation mLocation;
231 struct CTypeDescriptor *mType;
232 uint8_t mLogAlignment;
233 uint8_t mTypeCheckKind;
236 struct CVLABoundData {
237 struct CSourceLocation mLocation;
238 struct CTypeDescriptor *mType;
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;
247 struct CAlignmentAssumptionData {
248 struct CSourceLocation mLocation;
249 struct CSourceLocation mAssumptionLocation;
250 struct CTypeDescriptor *mType;
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);
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);
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);
267 static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
268 static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
270 static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
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);
279 /* Unused in this implementation, emitted by the C++ check dynamic type cast. */
280 intptr_t __ubsan_vptr_type_cache[128];
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);
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);
352 HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
354 char szLocation[LOCATION_MAXLEN];
355 char szLHS[NUMBER_MAXLEN];
356 char szRHS[NUMBER_MAXLEN];
360 if (isAlreadyReported(&pData->mLocation))
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);
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);
372 HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
374 char szLocation[LOCATION_MAXLEN];
375 char szOldValue[NUMBER_MAXLEN];
379 if (isAlreadyReported(&pData->mLocation))
382 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
383 DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
385 Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
386 szLocation, szOldValue, pData->mType->mTypeName);
390 HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
392 char szLocation[LOCATION_MAXLEN];
396 if (isAlreadyReported(&pData->mLocation))
399 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
401 Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
406 HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
408 char szLocation[LOCATION_MAXLEN];
413 if (isAlreadyReported(mLocation))
416 DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
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);
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);
431 HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
433 char szLocation[LOCATION_MAXLEN];
434 char szBound[NUMBER_MAXLEN];
438 if (isAlreadyReported(&pData->mLocation))
441 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
442 DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
444 Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
445 szLocation, szBound);
449 HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
451 char szLocation[LOCATION_MAXLEN];
452 char szIndex[NUMBER_MAXLEN];
456 if (isAlreadyReported(&pData->mLocation))
459 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
460 DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
462 Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
463 szLocation, szIndex, pData->mArrayType->mTypeName);
467 HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
469 char szLocation[LOCATION_MAXLEN];
470 char szLHS[NUMBER_MAXLEN];
471 char szRHS[NUMBER_MAXLEN];
475 if (isAlreadyReported(&pData->mLocation))
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);
482 if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
483 Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
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",
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);
497 HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
499 char szLocation[LOCATION_MAXLEN];
500 char szValue[NUMBER_MAXLEN];
504 if (isAlreadyReported(&pData->mLocation))
507 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
508 DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
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);
515 HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
517 char szLocation[LOCATION_MAXLEN];
521 if (isAlreadyReported(&pData->mLocation))
524 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
526 Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
527 szLocation, DeserializeBuiltinCheckKind(pData->mKind));
531 HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
533 char szLocation[LOCATION_MAXLEN];
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.
541 * For better diagnostic messages in the userland, users shall use
542 * the full upstream version shipped along with the compiler toolchain.
547 if (isAlreadyReported(&pData->mLocation))
550 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
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);
557 HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
559 char szLocation[LOCATION_MAXLEN];
562 * This is a minimal implementation without diving into C++
563 * specifics and (Itanium) ABI deserialization.
568 if (isAlreadyReported(&pData->mLocation))
571 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
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);
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);
583 HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
586 char szLocation[LOCATION_MAXLEN];
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.
599 if (isAlreadyReported(&pData->mLocation))
602 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
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);
610 HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
612 char szLocation[LOCATION_MAXLEN];
613 char szFrom[NUMBER_MAXLEN];
617 if (isAlreadyReported(&pData->mLocation))
620 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
621 DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
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);
628 HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
630 char szLocation[LOCATION_MAXLEN];
634 if (isAlreadyReported(&pData->mLocation))
637 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
639 Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
644 HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
646 char szLocation[LOCATION_MAXLEN];
647 char szAttributeLocation[LOCATION_MAXLEN];
651 if (isAlreadyReported(&pData->mLocation))
654 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
655 if (pData->mAttributeLocation.mFilename)
656 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
658 szAttributeLocation[0] = '\0';
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);
665 HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
667 char szLocation[LOCATION_MAXLEN];
668 char szAttributeLocation[LOCATION_MAXLEN];
671 ASSERT(pLocationPointer);
673 if (isAlreadyReported(pLocationPointer))
676 DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
677 if (pData->mAttributeLocation.mFilename)
678 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
680 szAttributeLocation[0] = '\0';
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);
687 HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
689 char szLocation[LOCATION_MAXLEN];
693 if (isAlreadyReported(&pData->mLocation))
696 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
698 Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
699 szLocation, ulBase, ulResult);
703 HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
705 char szLocation[LOCATION_MAXLEN];
706 char szAssumptionLocation[LOCATION_MAXLEN];
707 unsigned long ulRealPointer;
711 if (isAlreadyReported(&pData->mLocation))
714 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
716 ulRealPointer = ulPointer - ulOffset;
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);
725 Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx)\n",
726 szLocation, ulAlignment, ulRealPointer, ulOffset);
730 /* Definions of public symbols emitted by the instrumentation code */
732 __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
737 HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
741 __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
746 HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
750 __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
755 HandleAlignmentAssumption(false, pData, ulPointer, ulAlignment, ulOffset);
759 __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
764 HandleAlignmentAssumption(true, pData, ulPointer, ulAlignment, ulOffset);
768 __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
773 HandleBuiltinUnreachable(true, pData);
777 __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
782 HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
786 __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
791 HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
795 __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
800 HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
804 __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
809 HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
813 __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
818 HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
822 __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
827 HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
831 __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
836 HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
840 __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
845 HandleFloatCastOverflow(false, pData, ulFrom);
849 __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
854 HandleFloatCastOverflow(true, pData, ulFrom);
858 __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
863 HandleFunctionTypeMismatch(false, pData, ulFunction);
867 __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
872 HandleFunctionTypeMismatch(false, pData, ulFunction);
876 __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
881 HandleInvalidBuiltin(true, pData);
885 __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
890 HandleInvalidBuiltin(true, pData);
894 __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
899 HandleLoadInvalidValue(false, pData, ulValue);
903 __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
908 HandleLoadInvalidValue(true, pData, ulValue);
912 __ubsan_handle_missing_return(struct CUnreachableData *pData)
917 HandleMissingReturn(true, pData);
921 __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
926 HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
930 __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
935 HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
939 __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
944 HandleNegateOverflow(false, pData, ulOldValue);
948 __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
953 HandleNegateOverflow(true, pData, ulOldValue);
957 __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
962 HandleNonnullArg(false, pData);
966 __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
971 HandleNonnullArg(true, pData);
975 __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
979 ASSERT(pLocationPointer);
981 HandleNonnullReturn(false, pData, pLocationPointer);
985 __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
989 ASSERT(pLocationPointer);
991 HandleNonnullReturn(true, pData, pLocationPointer);
995 __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
1000 HandleNonnullArg(false, pData);
1004 __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
1009 HandleNonnullArg(true, pData);
1013 __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1017 ASSERT(pLocationPointer);
1019 HandleNonnullReturn(false, pData, pLocationPointer);
1023 __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1027 ASSERT(pLocationPointer);
1029 HandleNonnullReturn(true, pData, pLocationPointer);
1033 __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
1038 HandleOutOfBounds(false, pData, ulIndex);
1042 __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
1047 HandleOutOfBounds(true, pData, ulIndex);
1051 __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1056 HandlePointerOverflow(false, pData, ulBase, ulResult);
1060 __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1065 HandlePointerOverflow(true, pData, ulBase, ulResult);
1069 __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1074 HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
1078 __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1083 HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
1087 __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1092 HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
1096 __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1101 HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
1105 __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
1110 HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1114 __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
1119 HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1123 __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1128 HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1132 __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1137 HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1141 __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
1146 HandleVlaBoundNotPositive(false, pData, ulBound);
1150 __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
1155 HandleVlaBoundNotPositive(true, pData, ulBound);
1159 __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
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).
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
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.
1181 /* Local utility functions */
1184 Report(bool isFatal, const char *pFormat, ...)
1190 va_start(ap, pFormat);
1191 #if defined(_KERNEL)
1193 vpanic(pFormat, ap);
1195 vprintf(pFormat, ap);
1197 if (ubsan_flags == -1) {
1201 ubsan_flags = UBSAN_STDERR;
1203 if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
1204 for (p = buf; *p; p++) {
1207 SET(ubsan_flags, UBSAN_ABORT);
1210 CLR(ubsan_flags, UBSAN_ABORT);
1213 SET(ubsan_flags, UBSAN_STDERR);
1216 CLR(ubsan_flags, UBSAN_STDERR);
1219 SET(ubsan_flags, UBSAN_SYSLOG);
1222 CLR(ubsan_flags, UBSAN_SYSLOG);
1225 SET(ubsan_flags, UBSAN_STDOUT);
1228 CLR(ubsan_flags, UBSAN_STDOUT);
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)) {
1242 vprintf(pFormat, tmp);
1246 if (ISSET(ubsan_flags, UBSAN_STDERR)) {
1249 vfprintf(stderr, pFormat, tmp);
1253 if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
1256 struct syslog_data SyslogData = SYSLOG_DATA_INIT;
1257 ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
1260 if (isFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
1269 isAlreadyReported(struct CSourceLocation *pLocation)
1272 * This code is shared between libc, kernel and standalone usage.
1273 * It shall work in early bootstrap phase of both of them.
1276 uint32_t siOldValue;
1277 volatile uint32_t *pLine;
1281 pLine = &pLocation->mLine;
1284 siOldValue = *pLine;
1285 } while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
1287 return ISSET(siOldValue, ACK_REPORTED);
1291 zDeserializeTypeWidth(struct CTypeDescriptor *pType)
1297 switch (pType->mTypeKind) {
1299 zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
1302 zWidth = pType->mTypeInfo;
1305 Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
1309 /* Invalid width will be transformed to 0 */
1316 DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
1320 ASSERT(pLocation->mFilename);
1322 snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
1325 #ifdef __SIZEOF_INT128__
1327 DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
1329 char szBuf[3]; /* 'XX\0' */
1330 char rgNumber[sizeof(ulongest)];
1333 memcpy(rgNumber, &U128, sizeof(U128));
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--) {
1339 for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
1341 snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
1342 strlcat(pBuffer, szBuf, zBUfferLength);
1344 strlcat(pBuffer, ")", zBUfferLength);
1349 DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
1353 ASSERT(zBUfferLength > 0);
1355 ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1357 switch (zDeserializeTypeWidth(pType)) {
1359 ASSERT(0 && "Invalid codepath");
1361 #ifdef __SIZEOF_INT128__
1363 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1370 snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
1376 DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
1380 ASSERT(zBUfferLength > 0);
1382 ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1384 switch (zDeserializeTypeWidth(pType)) {
1386 ASSERT(0 && "Invalid codepath");
1388 #ifdef __SIZEOF_INT128__
1390 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1397 snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
1404 DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
1407 #ifdef __HAVE_LONG_DOUBLE
1412 ASSERT(zBUfferLength > 0);
1416 * This function handles 64-bit number over a pointer on 32-bit CPUs.
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));
1424 switch (zDeserializeTypeWidth(pType)) {
1425 #ifdef __HAVE_LONG_DOUBLE
1429 memcpy(&LD, pNumber, sizeof(long double));
1430 snprintf(pBuffer, zBUfferLength, "%Lg", LD);
1434 memcpy(&D, pNumber, sizeof(double));
1435 snprintf(pBuffer, zBUfferLength, "%g", D);
1441 DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1448 ASSERT(zBUfferLength > 0);
1450 ASSERT(sizeof(F) == sizeof(uint32_t));
1451 ASSERT(sizeof(D) == sizeof(uint64_t));
1453 switch (zDeserializeTypeWidth(pType)) {
1455 memcpy(&D, &ulNumber, sizeof(double));
1456 snprintf(pBuffer, zBUfferLength, "%g", D);
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.
1464 U32 = STATIC_CAST(uint32_t, ulNumber);
1465 memcpy(&F, &U32, sizeof(float));
1466 snprintf(pBuffer, zBUfferLength, "%g", F);
1469 snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
1476 llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1478 size_t zNumberWidth;
1484 zNumberWidth = zDeserializeTypeWidth(pType);
1485 switch (zNumberWidth) {
1487 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1490 #ifdef __SIZEOF_INT128__
1491 memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
1493 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1498 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1499 L = *REINTERPRET_CAST(int64_t *, ulNumber);
1501 L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
1505 L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
1508 L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
1511 L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
1519 llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1521 size_t zNumberWidth;
1526 zNumberWidth = zDeserializeTypeWidth(pType);
1527 switch (zNumberWidth) {
1529 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1532 #ifdef __SIZEOF_INT128__
1533 memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
1536 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1540 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1541 UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
1559 DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1561 size_t zNumberWidth;
1565 ASSERT(zBUfferLength > 0);
1567 ASSERT(pType->mTypeKind == KIND_FLOAT);
1569 zNumberWidth = zDeserializeTypeWidth(pType);
1570 switch (zNumberWidth) {
1572 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1574 #ifdef __HAVE_LONG_DOUBLE
1578 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1582 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1583 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1588 DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
1595 DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1600 ASSERT(zBUfferLength > 0);
1603 switch(pType->mTypeKind) {
1605 if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
1606 longest L = llliGetNumber(szLocation, pType, ulNumber);
1607 DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
1609 ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
1610 DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
1615 Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
1618 DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
1622 Report(true, "UBSan: Unknown Type in %s\n", szLocation);
1629 DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
1631 const char *rgczTypeCheckKinds[] = {
1634 "reference binding to",
1635 "member access within",
1637 "constructor call on",
1641 "cast to virtual base of",
1642 "_Nonnull binding to",
1643 "dynamic operation on"
1646 ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
1648 return rgczTypeCheckKinds[hhuTypeCheckKind];
1652 DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
1654 const char *rgczBuiltinCheckKinds[] = {
1659 ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
1661 return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
1665 DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
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
1677 ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
1679 return rgczCFICheckKinds[hhuCFICheckKind];
1683 isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1688 ASSERT(pType->mTypeKind == KIND_INTEGER);
1690 if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
1693 return llliGetNumber(szLocation, pType, ulNumber) < 0;
1697 isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
1702 ASSERT(pType->mTypeKind == KIND_INTEGER);
1704 return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;