The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_ubsan.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: f9e41492fe72962989ee92bf4a2d6c6a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.