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