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