Author: andrew
Date: Tue Nov  6 16:56:49 2018
New Revision: 340189
URL: https://svnweb.freebsd.org/changeset/base/340189

Log:
  Import the NetBSD micro ubsan code for the kernel.
  
  This imports revision 1.3 of common/lib/libc/misc/ubsan.c from NetBSD, the
  micro-ubsan code. It is an implementation of the Undefined Behavior
  Sanitizer runtime for use with recent clang and gcc.
  
  The uubsan code will be used in a later commit to implement kubsan to help
  find undefined behavior in the kernel.
  
  Sponsored by: DARPA, AFRL

Added:
  head/sys/kern/kern_ubsan.c   (contents, props changed)

Added: head/sys/kern/kern_ubsan.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/kern/kern_ubsan.c  Tue Nov  6 16:56:49 2018        (r340189)
@@ -0,0 +1,1638 @@
+/*     $NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $  */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * The micro UBSan implementation for the userland (uUBSan) and kernel 
(kUBSan).
+ * The uBSSan versions is suitable for inclusion into libc or used standalone
+ * with ATF tests.
+ *
+ * This file due to long symbol names generated by a compiler during the
+ * instrumentation process does not follow the KNF style with 80-column limit.
+ */
+
+#include <sys/cdefs.h>
+#if defined(_KERNEL)
+__KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
+#else
+__RCSID("$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
+#endif
+
+#if defined(_KERNEL)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stdarg.h>
+#define ASSERT(x) KASSERT(x)
+#else
+#if defined(_LIBC)
+#include "namespace.h"
+#endif
+#include <sys/param.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <math.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#if defined(_LIBC)
+#include "extern.h"
+#define ubsan_vsyslog vsyslog_ss
+#define ASSERT(x) _DIAGASSERT(x)
+#else
+#define ubsan_vsyslog vsyslog_r
+#define ASSERT(x) assert(x)
+#endif
+/* These macros are available in _KERNEL only */
+#define SET(t, f)      ((t) |= (f))
+#define ISSET(t, f)    ((t) & (f))
+#define CLR(t, f)      ((t) &= ~(f))
+#endif
+
+#define REINTERPRET_CAST(__dt, __st)   ((__dt)(__st))
+#define STATIC_CAST(__dt, __st)                ((__dt)(__st))
+
+#define ACK_REPORTED   __BIT(31)
+
+#define MUL_STRING     "*"
+#define PLUS_STRING    "+"
+#define MINUS_STRING   "-"
+#define DIVREM_STRING  "divrem"
+
+#define CFI_VCALL              0
+#define CFI_NVCALL             1
+#define CFI_DERIVEDCAST                2
+#define CFI_UNRELATEDCAST      3
+#define CFI_ICALL              4
+#define CFI_NVMFCALL           5
+#define CFI_VMFCALL            6
+
+#define NUMBER_MAXLEN  128
+#define LOCATION_MAXLEN        (PATH_MAX + 32 /* ':LINE:COLUMN' */)
+
+#define WIDTH_8                8
+#define WIDTH_16       16
+#define WIDTH_32       32
+#define WIDTH_64       64
+#define WIDTH_80       80
+#define WIDTH_96       96
+#define WIDTH_128      128
+
+#define NUMBER_SIGNED_BIT      1U
+
+#if __SIZEOF_INT128__
+typedef __int128 longest;
+typedef unsigned __int128 ulongest;
+#else
+typedef int64_t longest;
+typedef uint64_t ulongest;
+#endif
+
+#ifndef _KERNEL
+static int ubsan_flags = -1;
+#define UBSAN_ABORT    __BIT(0)
+#define UBSAN_STDOUT   __BIT(1)
+#define UBSAN_STDERR   __BIT(2)
+#define UBSAN_SYSLOG   __BIT(3)
+#endif
+
+/* Undefined Behavior specific defines and structures */
+
+#define KIND_INTEGER   0
+#define KIND_FLOAT     1
+#define KIND_UNKNOWN   UINT16_MAX
+
+struct CSourceLocation {
+       char *mFilename;
+       uint32_t mLine;
+       uint32_t mColumn;
+};
+
+struct CTypeDescriptor {
+       uint16_t mTypeKind;
+       uint16_t mTypeInfo;
+       uint8_t mTypeName[1];
+};
+
+struct COverflowData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+};
+
+struct CUnreachableData {
+       struct CSourceLocation mLocation;
+};
+
+struct CCFICheckFailData {
+       uint8_t mCheckKind;
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+};
+
+struct CDynamicTypeCacheMissData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+       void *mTypeInfo;
+       uint8_t mTypeCheckKind;
+};
+
+struct CFunctionTypeMismatchData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+};
+
+struct CInvalidBuiltinData {
+       struct CSourceLocation mLocation;
+       uint8_t mKind;
+};
+
+struct CInvalidValueData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+};
+
+struct CNonNullArgData {
+       struct CSourceLocation mLocation;
+       struct CSourceLocation mAttributeLocation;
+       int mArgIndex;
+};
+
+struct CNonNullReturnData {
+       struct CSourceLocation mAttributeLocation;
+};
+
+struct COutOfBoundsData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mArrayType;
+       struct CTypeDescriptor *mIndexType;
+};
+
+struct CPointerOverflowData {
+       struct CSourceLocation mLocation;
+};
+
+struct CShiftOutOfBoundsData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mLHSType;
+       struct CTypeDescriptor *mRHSType;
+};
+
+struct CTypeMismatchData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+       unsigned long mLogAlignment;
+       uint8_t mTypeCheckKind;
+};
+
+struct CTypeMismatchData_v1 {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+       uint8_t mLogAlignment;
+       uint8_t mTypeCheckKind;
+};
+
+struct CVLABoundData {
+       struct CSourceLocation mLocation;
+       struct CTypeDescriptor *mType;
+};
+
+struct CFloatCastOverflowData {
+       struct CSourceLocation mLocation;       /* This field exists in this 
struct since 2015 August 11th */
+       struct CTypeDescriptor *mFromType;
+       struct CTypeDescriptor *mToType;
+};
+
+/* Local utility functions */
+static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
+static bool isAlreadyReported(struct CSourceLocation *pLocation);
+static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
+static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct 
CSourceLocation *pLocation);
+#ifdef __SIZEOF_INT128__
+static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct 
CTypeDescriptor *pType, __uint128_t U128);
+#endif
+static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, 
struct CTypeDescriptor *pType, longest L);
+static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, 
struct CTypeDescriptor *pType, ulongest L);
+#ifndef _KERNEL
+static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, 
struct CTypeDescriptor *pType, unsigned long *pNumber);
+static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, 
struct CTypeDescriptor *pType, unsigned long ulNumber);
+#endif
+static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, 
unsigned long ulNumber);
+static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, 
unsigned long ulNumber);
+#ifndef _KERNEL
+static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t 
zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+#endif
+static void DeserializeNumber(char *szLocation, char *pBuffer, size_t 
zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
+static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
+static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
+static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, 
unsigned long ulNumber);
+static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor 
*pType, unsigned long ulNumber, size_t zWidth);
+
+/* Unused in this implementation, emitted by the C++ check dynamic type cast. 
*/
+intptr_t __ubsan_vptr_type_cache[128];
+
+/* Public symbols used in the instrumentation of the code generation part */
+void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long 
ulLHS, unsigned long ulRHS);
+void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned 
long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
+void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned 
long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long 
ProgramCounter, unsigned long FramePointer);
+void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned 
long ulValue, unsigned long ulValidVtable);
+void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, 
unsigned long ulValue, unsigned long ulValidVtable);
+void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long 
ulLHS, unsigned long ulRHS);
+void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, 
unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData 
*pData, unsigned long ulPointer, unsigned long ulHash);
+void __ubsan_handle_dynamic_type_cache_miss_abort(struct 
CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long 
ulHash);
+void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, 
unsigned long ulFrom);
+void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData 
*pData, unsigned long ulFrom);
+void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData 
*pData, unsigned long ulFunction);
+void __ubsan_handle_function_type_mismatch_abort(struct 
CFunctionTypeMismatchData *pData, unsigned long ulFunction);
+void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
+void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
+void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, 
unsigned long ulVal);
+void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, 
unsigned long ulVal);
+void __ubsan_handle_missing_return(struct CUnreachableData *pData);
+void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long 
ulLHS, unsigned long ulRHS);
+void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned 
long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long 
ulOldVal);
+void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, 
unsigned long ulOldVal);
+void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
+void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
+void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct 
CSourceLocation *pLocationPointer);
+void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, 
struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
+void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
+void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, 
struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData 
*pData, struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned 
long ulIndex);
+void __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, 
unsigned long ulIndex);
+void __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, 
unsigned long ulBase, unsigned long ulResult);
+void __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, 
unsigned long ulBase, unsigned long ulResult);
+void __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, 
unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData 
*pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long 
ulLHS, unsigned long ulRHS);
+void __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned 
long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned 
long ulPointer);
+void __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, 
unsigned long ulPointer);
+void __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, 
unsigned long ulPointer);
+void __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, 
unsigned long ulPointer);
+void __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, 
unsigned long ulBound);
+void __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, 
unsigned long ulBound);
+void __ubsan_get_current_report_data(const char **ppOutIssueKind, const char 
**ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t 
*pOutCol, char **ppOutMemoryAddr);
+
+static void HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned 
long ulLHS, unsigned long ulRHS, const char *szOperation);
+static void HandleNegateOverflow(bool isFatal, struct COverflowData *pData, 
unsigned long ulOldValue);
+static void HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData 
*pData);
+static void HandleTypeMismatch(bool isFatal, struct CSourceLocation 
*mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t 
mTypeCheckKind, unsigned long ulPointer);
+static void HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData 
*pData, unsigned long ulBound);
+static void HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, 
unsigned long ulIndex);
+static void HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData 
*pData, unsigned long ulLHS, unsigned long ulRHS);
+static void HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData 
*pData, unsigned long ulValue);
+static void HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData 
*pData);
+static void HandleFunctionTypeMismatch(bool isFatal, struct 
CFunctionTypeMismatchData *pData, unsigned long ulFunction);
+static void HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, 
unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, 
unsigned long *ProgramCounter, unsigned long *FramePointer);
+static void HandleDynamicTypeCacheMiss(bool isFatal, struct 
CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long 
ulHash);
+static void HandleFloatCastOverflow(bool isFatal, struct 
CFloatCastOverflowData *pData, unsigned long ulFrom);
+static void HandleMissingReturn(bool isFatal, struct CUnreachableData *pData);
+static void HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData);
+static void HandleNonnullReturn(bool isFatal, struct CNonNullReturnData 
*pData, struct CSourceLocation *pLocationPointer);
+static void HandlePointerOverflow(bool isFatal, struct CPointerOverflowData 
*pData, unsigned long ulBase, unsigned long ulResult);
+
+static void
+HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, 
unsigned long ulRHS, const char *szOperation)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szLHS[NUMBER_MAXLEN];
+       char szRHS[NUMBER_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mType, 
ulLHS);
+       DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mType, 
ulRHS);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, %s integer overflow: 
%s %s %s cannot be represented in type %s\n",
+              szLocation, ISSET(pData->mType->mTypeInfo, NUMBER_SIGNED_BIT) ? 
"signed" : "unsigned", szLHS, szOperation, szRHS, pData->mType->mTypeName);
+}
+
+static void
+HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long 
ulOldValue)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szOldValue[NUMBER_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, 
ulOldValue);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot 
be represented in type %s\n",
+              szLocation, szOldValue, pData->mType->mTypeName);
+}
+
+static void
+HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
+{
+       char szLocation[LOCATION_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, calling 
__builtin_unreachable()\n",
+              szLocation);
+}
+
+static void
+HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct 
CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, 
unsigned long ulPointer)
+{
+       char szLocation[LOCATION_MAXLEN];
+
+       ASSERT(mLocation);
+       ASSERT(mType);
+
+       if (isAlreadyReported(mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
+
+       if (ulPointer == 0) {
+               Report(isFatal, "UBSan: Undefined Behavior in %s, %s null 
pointer of type %s\n",
+                      szLocation, DeserializeTypeCheckKind(mTypeCheckKind), 
mType->mTypeName);
+       } else if ((mLogAlignment - 1) & ulPointer) {
+               Report(isFatal, "UBSan: Undefined Behavior in %s, %s misaligned 
address %p for type %s which requires %ld byte alignment\n",
+                      szLocation, DeserializeTypeCheckKind(mTypeCheckKind), 
REINTERPRET_CAST(void *, ulPointer), mType->mTypeName, mLogAlignment);
+       } else {
+               Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %p 
with insufficient space for an object of type %s\n",
+                      szLocation, DeserializeTypeCheckKind(mTypeCheckKind), 
REINTERPRET_CAST(void *, ulPointer), mType->mTypeName);
+       }
+}
+
+static void
+HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned 
long ulBound)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szBound[NUMBER_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, 
ulBound);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array 
bound value %s <= 0\n",
+              szLocation, szBound);
+}
+
+static void
+HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long 
ulIndex)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szIndex[NUMBER_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, 
pData->mIndexType, ulIndex);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of 
range for type %s\n",
+              szLocation, szIndex, pData->mArrayType->mTypeName);
+}
+
+static void
+HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, 
unsigned long ulLHS, unsigned long ulRHS)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szLHS[NUMBER_MAXLEN];
+       char szRHS[NUMBER_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mLHSType, 
ulLHS);
+       DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mRHSType, 
ulRHS);
+
+       if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
+               Report(isFatal, "UBSan: Undefined Behavior in %s, shift 
exponent %s is negative\n",
+                      szLocation, szRHS);
+       else if (isShiftExponentTooLarge(szLocation, pData->mRHSType, ulRHS, 
zDeserializeTypeWidth(pData->mLHSType)))
+               Report(isFatal, "UBSan: Undefined Behavior in %s, shift 
exponent %s is too large for %zu-bit type %s\n",
+                      szLocation, szRHS, 
zDeserializeTypeWidth(pData->mLHSType), pData->mLHSType->mTypeName);
+       else if (isNegativeNumber(szLocation, pData->mLHSType, ulLHS))
+               Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of 
negative value %s\n",
+                      szLocation, szLHS);
+       else
+               Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of 
%s by %s places cannot be represented in type %s\n",
+                      szLocation, szLHS, szRHS, pData->mLHSType->mTypeName);
+}
+
+static void
+HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned 
long ulValue)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szValue[NUMBER_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, 
ulValue);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, load of value %s is 
not a valid value for type %s\n",
+              szLocation, szValue, pData->mType->mTypeName);
+}
+
+static void
+HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
+{
+       char szLocation[LOCATION_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, 
which is not a valid argument\n",
+              szLocation, DeserializeBuiltinCheckKind(pData->mKind));
+}
+
+static void
+HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData 
*pData, unsigned long ulFunction)
+{
+       char szLocation[LOCATION_MAXLEN];
+
+       /*
+        * There is no a portable C solution to translate an address of a
+        * function to its name. On the cost of getting this routine simple
+        * and portable without ifdefs between the userland and the kernel
+        * just print the address of the function as-is.
+        *
+        * For better diagnostic messages in the userland, users shall use
+        * the full upstream version shipped along with the compiler toolchain.
+        */
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, call to function %#lx 
through pointer to incorrect function type %s\n",
+             szLocation, ulFunction, pData->mType->mTypeName);
+}
+
+static void
+HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long 
ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long 
*ProgramCounter, unsigned long *FramePointer)
+{
+       char szLocation[LOCATION_MAXLEN];
+
+       /*
+        * This is a minimal implementation without diving into C++
+        * specifics and (Itanium) ABI deserialization.
+        */
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+       if (pData->mCheckKind == CFI_ICALL || pData->mCheckKind == CFI_VMFCALL) 
{
+               Report(isFatal, "UBSan: Undefined Behavior in %s, control flow 
integrity check for type %s failed during %s (vtable address %#lx)\n",
+                     szLocation, pData->mType->mTypeName, 
DeserializeCFICheckKind(pData->mCheckKind), ulVtable);
+       } else {
+               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",
+                     szLocation, pData->mType->mTypeName, 
DeserializeCFICheckKind(pData->mCheckKind), ulVtable, *bValidVtable ? "valid" : 
"invalid", *FromUnrecoverableHandler ? "unrecoverable" : "recoverable", 
*ProgramCounter, *FramePointer);
+       }
+}
+
+static void
+HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData 
*pData, unsigned long ulPointer, unsigned long ulHash)
+{
+#if 0
+       char szLocation[LOCATION_MAXLEN];
+
+       /*
+        * Unimplemented.
+        *
+        * This UBSan handler is special as the check has to be impelemented
+        * in an implementation. In order to handle it there is need to
+        * introspect into C++ ABI internals (RTTI) and use low-level
+        * C++ runtime interfaces.
+        */
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %#lx which 
might not point to an object of type %s\n"
+             szLocation, DeserializeTypeCheckKind(pData->mTypeCheckKind), 
ulPointer, pData->mType);
+#endif
+}
+
+static void
+HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, 
unsigned long ulFrom)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szFrom[NUMBER_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, 
ulFrom);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, %s (of type %s) is 
outside the range of representable values of type %s\n",
+              szLocation, szFrom, pData->mFromType->mTypeName, 
pData->mToType->mTypeName);
+}
+
+static void
+HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
+{
+       char szLocation[LOCATION_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the 
end of a value-returning function without returning a value\n",
+              szLocation);
+}
+
+static void
+HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szAttributeLocation[LOCATION_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+       if (pData->mAttributeLocation.mFilename)
+               DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, 
&pData->mAttributeLocation);
+       else
+               szAttributeLocation[0] = '\0';
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer passed 
as argument %d, which is declared to never be null%s%s\n",
+              szLocation, pData->mArgIndex, 
pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", 
szAttributeLocation);
+}
+
+static void
+HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct 
CSourceLocation *pLocationPointer)
+{
+       char szLocation[LOCATION_MAXLEN];
+       char szAttributeLocation[LOCATION_MAXLEN];
+
+       ASSERT(pData);
+       ASSERT(pLocationPointer);
+
+       if (isAlreadyReported(pLocationPointer))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
+       if (pData->mAttributeLocation.mFilename)
+               DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, 
&pData->mAttributeLocation);
+       else
+               szAttributeLocation[0] = '\0';
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer returned 
from function declared to never return null%s%s\n",
+              szLocation, pData->mAttributeLocation.mFilename ? ", 
nonnull/_Nonnull specified in " : "", szAttributeLocation);
+}
+
+static void
+HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, 
unsigned long ulBase, unsigned long ulResult)
+{
+       char szLocation[LOCATION_MAXLEN];
+
+       ASSERT(pData);
+
+       if (isAlreadyReported(&pData->mLocation))
+               return;
+
+       DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
+
+       Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression 
with base %#lx overflowed to %#lx\n",
+              szLocation, ulBase, ulResult);
+}
+
+/* Definions of public symbols emitted by the instrumentation code */
+void
+__ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, 
unsigned long ulRHS)
+{
+
+       ASSERT(pData);
+
+       HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
+}
+
+void
+__ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long 
ulLHS, unsigned long ulRHS)
+{
+
+       ASSERT(pData);
+
+       HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
+}
+
+void
+__ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleBuiltinUnreachable(true, pData);
+}
+
+void
+__ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long 
ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long 
ProgramCounter, unsigned long FramePointer)
+{
+
+       ASSERT(pData);
+
+       HandleCFIBadType(false, pData, ulVtable, &bValidVtable, 
&FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
+}
+
+void
+__ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long 
ulValue, unsigned long ulValidVtable)
+{
+
+       ASSERT(pData);
+
+       HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
+}
+
+void
+__ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned 
long ulValue, unsigned long ulValidVtable)
+{
+
+       ASSERT(pData);
+
+       HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
+}
+
+void
+__ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long 
ulLHS, unsigned long ulRHS)
+{
+
+       ASSERT(pData);
+
+       HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
+}
+
+void
+__ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned 
long ulLHS, unsigned long ulRHS)
+{
+
+       ASSERT(pData);
+
+       HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
+}
+
+void
+__ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData 
*pData, unsigned long ulPointer, unsigned long ulHash)
+{
+
+       ASSERT(pData);
+
+       HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
+}
+
+void
+__ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData 
*pData, unsigned long ulPointer, unsigned long ulHash)
+{
+
+       ASSERT(pData);
+
+       HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
+}
+
+void
+__ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, 
unsigned long ulFrom)
+{
+
+       ASSERT(pData);
+
+       HandleFloatCastOverflow(false, pData, ulFrom);
+}
+
+void
+__ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, 
unsigned long ulFrom)
+{
+
+       ASSERT(pData);
+
+       HandleFloatCastOverflow(true, pData, ulFrom);
+}
+
+void
+__ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, 
unsigned long ulFunction)
+{
+
+       ASSERT(pData);
+
+       HandleFunctionTypeMismatch(false, pData, ulFunction);
+}
+
+void
+__ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData 
*pData, unsigned long ulFunction)
+{
+
+       ASSERT(pData);
+
+       HandleFunctionTypeMismatch(false, pData, ulFunction);
+}
+
+void
+__ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleInvalidBuiltin(true, pData);
+}
+
+void
+__ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleInvalidBuiltin(true, pData);
+}
+
+void
+__ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned 
long ulValue)
+{
+
+       ASSERT(pData);
+
+       HandleLoadInvalidValue(false, pData, ulValue);
+}
+
+void
+__ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, 
unsigned long ulValue)
+{
+
+       ASSERT(pData);
+
+       HandleLoadInvalidValue(true, pData, ulValue);
+}
+
+void
+__ubsan_handle_missing_return(struct CUnreachableData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleMissingReturn(true, pData);
+}
+
+void
+__ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, 
unsigned long ulRHS)
+{
+
+       ASSERT(pData);
+
+       HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
+}
+
+void
+__ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long 
ulLHS, unsigned long ulRHS)
+{
+
+       ASSERT(pData);
+
+       HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
+}
+
+void
+__ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long 
ulOldValue)
+{
+
+       ASSERT(pData);
+
+       HandleNegateOverflow(false, pData, ulOldValue);
+}
+
+void
+__ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned 
long ulOldValue)
+{
+
+       ASSERT(pData);
+
+       HandleNegateOverflow(true, pData, ulOldValue);
+}
+
+void
+__ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleNonnullArg(false, pData);
+}
+
+void
+__ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleNonnullArg(true, pData);
+}
+
+void
+__ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct 
CSourceLocation *pLocationPointer)
+{
+
+       ASSERT(pData);
+       ASSERT(pLocationPointer);
+
+       HandleNonnullReturn(false, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, 
struct CSourceLocation *pLocationPointer)
+{
+
+       ASSERT(pData);
+       ASSERT(pLocationPointer);
+
+       HandleNonnullReturn(true, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleNonnullArg(false, pData);
+}
+
+void
+__ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
+{
+
+       ASSERT(pData);
+
+       HandleNonnullArg(true, pData);
+}
+
+void
+__ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct 
CSourceLocation *pLocationPointer)
+{
+
+       ASSERT(pData);
+       ASSERT(pLocationPointer);
+
+       HandleNonnullReturn(false, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, 
struct CSourceLocation *pLocationPointer)
+{
+
+       ASSERT(pData);
+       ASSERT(pLocationPointer);
+
+       HandleNonnullReturn(true, pData, pLocationPointer);
+}
+
+void
+__ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long 
ulIndex)
+{
+
+       ASSERT(pData);
+
+       HandleOutOfBounds(false, pData, ulIndex);
+}
+
+void
+__ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned 
long ulIndex)
+{
+
+       ASSERT(pData);
+
+       HandleOutOfBounds(true, pData, ulIndex);
+}
+
+void
+__ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned 
long ulBase, unsigned long ulResult)
+{
+
+       ASSERT(pData);
+
+       HandlePointerOverflow(false, pData, ulBase, ulResult);
+}
+
+void
+__ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, 
unsigned long ulBase, unsigned long ulResult)
+{
+
+       ASSERT(pData);
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to