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