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