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