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