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.
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
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.
38 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
44 __RCSID("$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
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))
63 #include "namespace.h"
65 #include <sys/param.h>
80 #define ubsan_vsyslog vsyslog_ss
81 #define ASSERT(x) _DIAGASSERT(x)
83 #define ubsan_vsyslog vsyslog_r
84 #define ASSERT(x) assert(x)
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))
92 #define REINTERPRET_CAST(__dt, __st) ((__dt)(__st))
93 #define STATIC_CAST(__dt, __st) ((__dt)(__st))
95 #define ACK_REPORTED __BIT(31)
97 #define MUL_STRING "*"
98 #define PLUS_STRING "+"
99 #define MINUS_STRING "-"
100 #define DIVREM_STRING "divrem"
104 #define CFI_DERIVEDCAST 2
105 #define CFI_UNRELATEDCAST 3
107 #define CFI_NVMFCALL 5
108 #define CFI_VMFCALL 6
110 #define NUMBER_MAXLEN 128
111 #define LOCATION_MAXLEN (PATH_MAX + 32 /* ':LINE:COLUMN' */)
119 #define WIDTH_128 128
121 #define NUMBER_SIGNED_BIT 1U
123 #if __SIZEOF_INT128__
124 typedef __int128 longest;
125 typedef unsigned __int128 ulongest;
127 typedef int64_t longest;
128 typedef uint64_t ulongest;
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)
139 /* Undefined Behavior specific defines and structures */
141 #define KIND_INTEGER 0
143 #define KIND_UNKNOWN UINT16_MAX
145 struct CSourceLocation {
151 struct CTypeDescriptor {
154 uint8_t mTypeName[1];
157 struct COverflowData {
158 struct CSourceLocation mLocation;
159 struct CTypeDescriptor *mType;
162 struct CUnreachableData {
163 struct CSourceLocation mLocation;
166 struct CCFICheckFailData {
168 struct CSourceLocation mLocation;
169 struct CTypeDescriptor *mType;
172 struct CDynamicTypeCacheMissData {
173 struct CSourceLocation mLocation;
174 struct CTypeDescriptor *mType;
176 uint8_t mTypeCheckKind;
179 struct CFunctionTypeMismatchData {
180 struct CSourceLocation mLocation;
181 struct CTypeDescriptor *mType;
184 struct CInvalidBuiltinData {
185 struct CSourceLocation mLocation;
189 struct CInvalidValueData {
190 struct CSourceLocation mLocation;
191 struct CTypeDescriptor *mType;
194 struct CNonNullArgData {
195 struct CSourceLocation mLocation;
196 struct CSourceLocation mAttributeLocation;
200 struct CNonNullReturnData {
201 struct CSourceLocation mAttributeLocation;
204 struct COutOfBoundsData {
205 struct CSourceLocation mLocation;
206 struct CTypeDescriptor *mArrayType;
207 struct CTypeDescriptor *mIndexType;
210 struct CPointerOverflowData {
211 struct CSourceLocation mLocation;
214 struct CShiftOutOfBoundsData {
215 struct CSourceLocation mLocation;
216 struct CTypeDescriptor *mLHSType;
217 struct CTypeDescriptor *mRHSType;
220 struct CTypeMismatchData {
221 struct CSourceLocation mLocation;
222 struct CTypeDescriptor *mType;
223 unsigned long mLogAlignment;
224 uint8_t mTypeCheckKind;
227 struct CTypeMismatchData_v1 {
228 struct CSourceLocation mLocation;
229 struct CTypeDescriptor *mType;
230 uint8_t mLogAlignment;
231 uint8_t mTypeCheckKind;
234 struct CVLABoundData {
235 struct CSourceLocation mLocation;
236 struct CTypeDescriptor *mType;
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;
245 struct CAlignmentAssumptionData {
246 struct CSourceLocation mLocation;
247 struct CSourceLocation mAssumptionLocation;
248 struct CTypeDescriptor *mType;
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);
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);
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);
265 static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
266 static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
268 static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
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);
277 /* Unused in this implementation, emitted by the C++ check dynamic type cast. */
278 intptr_t __ubsan_vptr_type_cache[128];
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);
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);
350 HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
352 char szLocation[LOCATION_MAXLEN];
353 char szLHS[NUMBER_MAXLEN];
354 char szRHS[NUMBER_MAXLEN];
358 if (isAlreadyReported(&pData->mLocation))
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);
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);
370 HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
372 char szLocation[LOCATION_MAXLEN];
373 char szOldValue[NUMBER_MAXLEN];
377 if (isAlreadyReported(&pData->mLocation))
380 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
381 DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
383 Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
384 szLocation, szOldValue, pData->mType->mTypeName);
388 HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
390 char szLocation[LOCATION_MAXLEN];
394 if (isAlreadyReported(&pData->mLocation))
397 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
399 Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
404 HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
406 char szLocation[LOCATION_MAXLEN];
411 if (isAlreadyReported(mLocation))
414 DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
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);
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);
429 HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
431 char szLocation[LOCATION_MAXLEN];
432 char szBound[NUMBER_MAXLEN];
436 if (isAlreadyReported(&pData->mLocation))
439 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
440 DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
442 Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
443 szLocation, szBound);
447 HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
449 char szLocation[LOCATION_MAXLEN];
450 char szIndex[NUMBER_MAXLEN];
454 if (isAlreadyReported(&pData->mLocation))
457 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
458 DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
460 Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
461 szLocation, szIndex, pData->mArrayType->mTypeName);
465 HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
467 char szLocation[LOCATION_MAXLEN];
468 char szLHS[NUMBER_MAXLEN];
469 char szRHS[NUMBER_MAXLEN];
473 if (isAlreadyReported(&pData->mLocation))
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);
480 if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
481 Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
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",
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);
495 HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
497 char szLocation[LOCATION_MAXLEN];
498 char szValue[NUMBER_MAXLEN];
502 if (isAlreadyReported(&pData->mLocation))
505 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
506 DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
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);
513 HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
515 char szLocation[LOCATION_MAXLEN];
519 if (isAlreadyReported(&pData->mLocation))
522 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
524 Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
525 szLocation, DeserializeBuiltinCheckKind(pData->mKind));
529 HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
531 char szLocation[LOCATION_MAXLEN];
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.
539 * For better diagnostic messages in the userland, users shall use
540 * the full upstream version shipped along with the compiler toolchain.
545 if (isAlreadyReported(&pData->mLocation))
548 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
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);
555 HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
557 char szLocation[LOCATION_MAXLEN];
560 * This is a minimal implementation without diving into C++
561 * specifics and (Itanium) ABI deserialization.
566 if (isAlreadyReported(&pData->mLocation))
569 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
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);
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);
581 HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
584 char szLocation[LOCATION_MAXLEN];
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.
597 if (isAlreadyReported(&pData->mLocation))
600 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
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);
608 HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
610 char szLocation[LOCATION_MAXLEN];
611 char szFrom[NUMBER_MAXLEN];
615 if (isAlreadyReported(&pData->mLocation))
618 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
619 DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
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);
626 HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
628 char szLocation[LOCATION_MAXLEN];
632 if (isAlreadyReported(&pData->mLocation))
635 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
637 Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
642 HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
644 char szLocation[LOCATION_MAXLEN];
645 char szAttributeLocation[LOCATION_MAXLEN];
649 if (isAlreadyReported(&pData->mLocation))
652 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
653 if (pData->mAttributeLocation.mFilename)
654 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
656 szAttributeLocation[0] = '\0';
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);
663 HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
665 char szLocation[LOCATION_MAXLEN];
666 char szAttributeLocation[LOCATION_MAXLEN];
669 ASSERT(pLocationPointer);
671 if (isAlreadyReported(pLocationPointer))
674 DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
675 if (pData->mAttributeLocation.mFilename)
676 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
678 szAttributeLocation[0] = '\0';
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);
685 HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
687 char szLocation[LOCATION_MAXLEN];
691 if (isAlreadyReported(&pData->mLocation))
694 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
696 Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
697 szLocation, ulBase, ulResult);
701 HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
703 char szLocation[LOCATION_MAXLEN];
704 char szAssumptionLocation[LOCATION_MAXLEN];
705 unsigned long ulRealPointer;
709 if (isAlreadyReported(&pData->mLocation))
712 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
714 ulRealPointer = ulPointer - ulOffset;
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);
723 Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx)\n",
724 szLocation, ulAlignment, ulRealPointer, ulOffset);
728 /* Definions of public symbols emitted by the instrumentation code */
730 __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
735 HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
739 __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
744 HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
748 __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
753 HandleAlignmentAssumption(false, pData, ulPointer, ulAlignment, ulOffset);
757 __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
762 HandleAlignmentAssumption(true, pData, ulPointer, ulAlignment, ulOffset);
766 __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
771 HandleBuiltinUnreachable(true, pData);
775 __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
780 HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
784 __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
789 HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
793 __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
798 HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
802 __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
807 HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
811 __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
816 HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
820 __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
825 HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
829 __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
834 HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
838 __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
843 HandleFloatCastOverflow(false, pData, ulFrom);
847 __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
852 HandleFloatCastOverflow(true, pData, ulFrom);
856 __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
861 HandleFunctionTypeMismatch(false, pData, ulFunction);
865 __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
870 HandleFunctionTypeMismatch(false, pData, ulFunction);
874 __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
879 HandleInvalidBuiltin(true, pData);
883 __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
888 HandleInvalidBuiltin(true, pData);
892 __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
897 HandleLoadInvalidValue(false, pData, ulValue);
901 __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
906 HandleLoadInvalidValue(true, pData, ulValue);
910 __ubsan_handle_missing_return(struct CUnreachableData *pData)
915 HandleMissingReturn(true, pData);
919 __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
924 HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
928 __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
933 HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
937 __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
942 HandleNegateOverflow(false, pData, ulOldValue);
946 __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
951 HandleNegateOverflow(true, pData, ulOldValue);
955 __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
960 HandleNonnullArg(false, pData);
964 __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
969 HandleNonnullArg(true, pData);
973 __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
977 ASSERT(pLocationPointer);
979 HandleNonnullReturn(false, pData, pLocationPointer);
983 __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
987 ASSERT(pLocationPointer);
989 HandleNonnullReturn(true, pData, pLocationPointer);
993 __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
998 HandleNonnullArg(false, pData);
1002 __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
1007 HandleNonnullArg(true, pData);
1011 __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1015 ASSERT(pLocationPointer);
1017 HandleNonnullReturn(false, pData, pLocationPointer);
1021 __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1025 ASSERT(pLocationPointer);
1027 HandleNonnullReturn(true, pData, pLocationPointer);
1031 __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
1036 HandleOutOfBounds(false, pData, ulIndex);
1040 __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
1045 HandleOutOfBounds(true, pData, ulIndex);
1049 __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1054 HandlePointerOverflow(false, pData, ulBase, ulResult);
1058 __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1063 HandlePointerOverflow(true, pData, ulBase, ulResult);
1067 __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1072 HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
1076 __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1081 HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
1085 __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1090 HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
1094 __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1099 HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
1103 __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
1108 HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1112 __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
1117 HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1121 __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1126 HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1130 __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1135 HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1139 __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
1144 HandleVlaBoundNotPositive(false, pData, ulBound);
1148 __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
1153 HandleVlaBoundNotPositive(true, pData, ulBound);
1157 __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
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).
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
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.
1179 /* Local utility functions */
1182 Report(bool isFatal, const char *pFormat, ...)
1188 va_start(ap, pFormat);
1189 #if defined(_KERNEL)
1191 vpanic(pFormat, ap);
1193 vprintf(pFormat, ap);
1195 if (ubsan_flags == -1) {
1199 ubsan_flags = UBSAN_STDERR;
1201 if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
1202 for (p = buf; *p; p++) {
1205 SET(ubsan_flags, UBSAN_ABORT);
1208 CLR(ubsan_flags, UBSAN_ABORT);
1211 SET(ubsan_flags, UBSAN_STDERR);
1214 CLR(ubsan_flags, UBSAN_STDERR);
1217 SET(ubsan_flags, UBSAN_SYSLOG);
1220 CLR(ubsan_flags, UBSAN_SYSLOG);
1223 SET(ubsan_flags, UBSAN_STDOUT);
1226 CLR(ubsan_flags, UBSAN_STDOUT);
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)) {
1240 vprintf(pFormat, tmp);
1244 if (ISSET(ubsan_flags, UBSAN_STDERR)) {
1247 vfprintf(stderr, pFormat, tmp);
1251 if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
1254 struct syslog_data SyslogData = SYSLOG_DATA_INIT;
1255 ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
1258 if (isFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
1267 isAlreadyReported(struct CSourceLocation *pLocation)
1270 * This code is shared between libc, kernel and standalone usage.
1271 * It shall work in early bootstrap phase of both of them.
1274 uint32_t siOldValue;
1275 volatile uint32_t *pLine;
1279 pLine = &pLocation->mLine;
1282 siOldValue = *pLine;
1283 } while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
1285 return ISSET(siOldValue, ACK_REPORTED);
1289 zDeserializeTypeWidth(struct CTypeDescriptor *pType)
1295 switch (pType->mTypeKind) {
1297 zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
1300 zWidth = pType->mTypeInfo;
1303 Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
1307 /* Invalid width will be transformed to 0 */
1314 DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
1318 ASSERT(pLocation->mFilename);
1320 snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
1323 #ifdef __SIZEOF_INT128__
1325 DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
1327 char szBuf[3]; /* 'XX\0' */
1328 char rgNumber[sizeof(ulongest)];
1331 memcpy(rgNumber, &U128, sizeof(U128));
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--) {
1337 for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
1339 snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
1340 strlcat(pBuffer, szBuf, zBUfferLength);
1342 strlcat(pBuffer, ")", zBUfferLength);
1347 DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
1351 ASSERT(zBUfferLength > 0);
1353 ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1355 switch (zDeserializeTypeWidth(pType)) {
1357 ASSERT(0 && "Invalid codepath");
1359 #ifdef __SIZEOF_INT128__
1361 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1368 snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
1374 DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
1378 ASSERT(zBUfferLength > 0);
1380 ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1382 switch (zDeserializeTypeWidth(pType)) {
1384 ASSERT(0 && "Invalid codepath");
1386 #ifdef __SIZEOF_INT128__
1388 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1395 snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
1402 DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
1405 #ifdef __HAVE_LONG_DOUBLE
1410 ASSERT(zBUfferLength > 0);
1414 * This function handles 64-bit number over a pointer on 32-bit CPUs.
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));
1422 switch (zDeserializeTypeWidth(pType)) {
1423 #ifdef __HAVE_LONG_DOUBLE
1427 memcpy(&LD, pNumber, sizeof(long double));
1428 snprintf(pBuffer, zBUfferLength, "%Lg", LD);
1432 memcpy(&D, pNumber, sizeof(double));
1433 snprintf(pBuffer, zBUfferLength, "%g", D);
1439 DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1446 ASSERT(zBUfferLength > 0);
1448 ASSERT(sizeof(F) == sizeof(uint32_t));
1449 ASSERT(sizeof(D) == sizeof(uint64_t));
1451 switch (zDeserializeTypeWidth(pType)) {
1453 memcpy(&D, &ulNumber, sizeof(double));
1454 snprintf(pBuffer, zBUfferLength, "%g", D);
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.
1462 U32 = STATIC_CAST(uint32_t, ulNumber);
1463 memcpy(&F, &U32, sizeof(float));
1464 snprintf(pBuffer, zBUfferLength, "%g", F);
1467 snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
1474 llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1476 size_t zNumberWidth;
1482 zNumberWidth = zDeserializeTypeWidth(pType);
1483 switch (zNumberWidth) {
1485 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1488 #ifdef __SIZEOF_INT128__
1489 memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
1491 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1496 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1497 L = *REINTERPRET_CAST(int64_t *, ulNumber);
1499 L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
1503 L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
1506 L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
1509 L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
1517 llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1519 size_t zNumberWidth;
1524 zNumberWidth = zDeserializeTypeWidth(pType);
1525 switch (zNumberWidth) {
1527 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1530 #ifdef __SIZEOF_INT128__
1531 memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
1534 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1538 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1539 UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
1557 DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1559 size_t zNumberWidth;
1563 ASSERT(zBUfferLength > 0);
1565 ASSERT(pType->mTypeKind == KIND_FLOAT);
1567 zNumberWidth = zDeserializeTypeWidth(pType);
1568 switch (zNumberWidth) {
1570 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1572 #ifdef __HAVE_LONG_DOUBLE
1576 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1580 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1581 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1586 DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
1593 DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1598 ASSERT(zBUfferLength > 0);
1601 switch(pType->mTypeKind) {
1603 if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
1604 longest L = llliGetNumber(szLocation, pType, ulNumber);
1605 DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
1607 ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
1608 DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
1613 Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
1616 DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
1620 Report(true, "UBSan: Unknown Type in %s\n", szLocation);
1627 DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
1629 const char *rgczTypeCheckKinds[] = {
1632 "reference binding to",
1633 "member access within",
1635 "constructor call on",
1639 "cast to virtual base of",
1640 "_Nonnull binding to",
1641 "dynamic operation on"
1644 ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
1646 return rgczTypeCheckKinds[hhuTypeCheckKind];
1650 DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
1652 const char *rgczBuiltinCheckKinds[] = {
1657 ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
1659 return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
1663 DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
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
1675 ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
1677 return rgczCFICheckKinds[hhuCFICheckKind];
1681 isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1686 ASSERT(pType->mTypeKind == KIND_INTEGER);
1688 if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
1691 return llliGetNumber(szLocation, pType, ulNumber) < 0;
1695 isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
1700 ASSERT(pType->mTypeKind == KIND_INTEGER);
1702 return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;