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