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