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