mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Remove undefined behaviors
This commit is contained in:
parent
4864565198
commit
b3838173ec
51 changed files with 756 additions and 1302 deletions
|
@ -612,7 +612,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
if (pun.d && prec < 13) {
|
||||
pun.u[1] |= 0x100000;
|
||||
if (prec < 5) {
|
||||
ui = 1 << ((5 - prec) * 4 - 1);
|
||||
ui = 1u << ((5 - prec) * 4 - 1);
|
||||
if (pun.u[1] & ui) {
|
||||
if (pun.u[1] & ((ui - 1) | (ui << 1)) || pun.u[0]) {
|
||||
pun.u[1] += ui;
|
||||
|
@ -631,7 +631,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
}
|
||||
} else {
|
||||
i1 = (13 - prec) * 4;
|
||||
ui = 1 << (i1 - 1);
|
||||
ui = 1u << (i1 - 1);
|
||||
if (pun.u[0] & ui && pun.u[0] & ((ui - 1) | (ui << 1))) {
|
||||
pun.u[0] += ui;
|
||||
if (!(pun.u[0] >> i1)) goto BumpIt;
|
||||
|
@ -640,12 +640,13 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
}
|
||||
} else {
|
||||
if ((ui = pun.u[0])) {
|
||||
for (prec = 6; (ui = (ui << 4) & 0xffffffff); ++prec) {
|
||||
}
|
||||
ui = __builtin_ctz(ui);
|
||||
prec = 6 + ((32 - ROUNDDOWN(ui, 4)) >> 2) - 1;
|
||||
} else if ((ui = pun.u[1] & 0xfffff)) {
|
||||
ui = __builtin_ctz(ui);
|
||||
prec = (20 - ROUNDDOWN(ui, 4)) >> 2;
|
||||
} else {
|
||||
for (prec = 0, ui = pun.u[1] & 0xfffff; ui;
|
||||
++prec, ui = (ui << 4) & 0xfffff) {
|
||||
}
|
||||
prec = 0;
|
||||
}
|
||||
}
|
||||
bw = 1;
|
||||
|
|
|
@ -68,11 +68,6 @@ o/$(MODE)/libc/fmt/filetimetotimeval.o: \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-O3
|
||||
|
||||
o/$(MODE)/libc/fmt/itoa64radix10.greg.o \
|
||||
o/$(MODE)/libc/fmt/itoa128radix10.greg.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fwrapv
|
||||
|
||||
LIBC_FMT_LIBS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)))
|
||||
LIBC_FMT_SRCS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_FMT_HDRS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_HDRS))
|
||||
|
|
|
@ -49,5 +49,5 @@ noinline size_t uint128toarray_radix10(uint128_t i, char *a) {
|
|||
size_t int128toarray_radix10(int128_t i, char *a) {
|
||||
if (i >= 0) return uint128toarray_radix10(i, a);
|
||||
*a++ = '-';
|
||||
return 1 + uint128toarray_radix10(-i, a);
|
||||
return 1 + uint128toarray_radix10(-(uint128_t)i, a);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ noinline size_t uint64toarray(uint64_t i, char *a, int r) {
|
|||
size_t int64toarray(int64_t i, char *a, int r) {
|
||||
if (i < 0) {
|
||||
*a++ = '-';
|
||||
i = -i;
|
||||
i = -(uint64_t)i;
|
||||
}
|
||||
return uint64toarray(i, a, r);
|
||||
}
|
||||
|
|
|
@ -27,14 +27,10 @@
|
|||
* @return bytes written w/o nul
|
||||
*/
|
||||
noinline size_t uint64toarray_radix10(uint64_t i, char a[hasatleast 21]) {
|
||||
size_t j;
|
||||
j = 0;
|
||||
size_t j = 0;
|
||||
do {
|
||||
struct {
|
||||
uint64_t q, r;
|
||||
} x = {i / 10, i % 10};
|
||||
a[j++] = x.r + '0';
|
||||
i = x.q;
|
||||
a[j++] = i % 10 + '0';
|
||||
i = i / 10;
|
||||
} while (i > 0);
|
||||
a[j] = '\0';
|
||||
reverse(a, j);
|
||||
|
@ -49,5 +45,5 @@ noinline size_t uint64toarray_radix10(uint64_t i, char a[hasatleast 21]) {
|
|||
size_t int64toarray_radix10(int64_t i, char a[hasatleast 21]) {
|
||||
if (i >= 0) return uint64toarray_radix10(i, a);
|
||||
*a++ = '-';
|
||||
return 1 + uint64toarray_radix10(-i, a);
|
||||
return 1 + uint64toarray_radix10(-(uint64_t)i, a);
|
||||
}
|
||||
|
|
|
@ -584,6 +584,13 @@ typedef uint64_t uintmax_t;
|
|||
#define noasan
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
|
||||
__has_attribute(__no_sanitize_undefined__)
|
||||
#define noubsan __attribute__((__no_sanitize_undefined__))
|
||||
#else
|
||||
#define noubsan
|
||||
#endif
|
||||
|
||||
#ifndef unreachable
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define unreachable __builtin_unreachable()
|
||||
|
|
|
@ -169,7 +169,7 @@ static void *__asan_memset(void *p, int c, size_t n) {
|
|||
size_t i;
|
||||
uint64_t x;
|
||||
b = p;
|
||||
x = 0x0101010101010101 * (c & 255);
|
||||
x = 0x0101010101010101ul * (c & 255);
|
||||
switch (n) {
|
||||
case 0:
|
||||
return p;
|
||||
|
|
|
@ -41,13 +41,11 @@ $(LIBC_INTRIN_A).pkg: \
|
|||
$(LIBC_INTRIN_A_OBJS) \
|
||||
$(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(LIBC_INTRIN_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(NO_MAGIC) \
|
||||
-O3
|
||||
|
||||
o/$(MODE)/libc/intrin/asan.o: \
|
||||
o/$(MODE)/libc/intrin/asan.o \
|
||||
o/$(MODE)/libc/intrin/ubsan.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector \
|
||||
-mgeneral-regs-only \
|
||||
-O2
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ void(pabsd)(uint32_t a[4], const int32_t b[4]) {
|
|||
unsigned i;
|
||||
uint32_t r[4];
|
||||
for (i = 0; i < 4; ++i) {
|
||||
r[i] = ABS(b[i]);
|
||||
r[i] = b[i] >= 0 ? b[i] : -(uint32_t)b[i];
|
||||
}
|
||||
memcpy(a, r, 16);
|
||||
}
|
||||
|
|
|
@ -27,9 +27,11 @@
|
|||
* @param 𝑐 [r/o] supplies second input vector
|
||||
* @mayalias
|
||||
*/
|
||||
void(paddd)(int32_t a[4], const int32_t b[4], const int32_t c[4]) {
|
||||
void(paddd)(uint32_t a[4], const uint32_t b[4], const uint32_t c[4]) {
|
||||
unsigned i;
|
||||
int32_t r[4];
|
||||
for (i = 0; i < 4; ++i) r[i] = b[i] + c[i];
|
||||
uint32_t r[4];
|
||||
for (i = 0; i < 4; ++i) {
|
||||
r[i] = b[i] + c[i];
|
||||
}
|
||||
memcpy(a, r, 16);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void paddd(int32_t[4], const int32_t[4], const int32_t[4]);
|
||||
void paddd(uint32_t[4], const uint32_t[4], const uint32_t[4]);
|
||||
|
||||
#define paddd(A, B, C) \
|
||||
INTRIN_SSEVEX_X_X_X_(paddd, SSE2, "paddd", INTRIN_COMMUTATIVE, A, B, C)
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
* @param 𝑐 [r/o] supplies second input vector
|
||||
* @mayalias
|
||||
*/
|
||||
void(paddq)(int64_t a[2], const int64_t b[2], const int64_t c[2]) {
|
||||
void(paddq)(uint64_t a[2], const uint64_t b[2], const uint64_t c[2]) {
|
||||
unsigned i;
|
||||
int64_t r[2];
|
||||
uint64_t r[2];
|
||||
for (i = 0; i < 2; ++i) r[i] = b[i] + c[i];
|
||||
memcpy(a, r, 16);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void paddq(int64_t[2], const int64_t[2], const int64_t[2]);
|
||||
void paddq(uint64_t[2], const uint64_t[2], const uint64_t[2]);
|
||||
|
||||
#define paddq(A, B, C) \
|
||||
INTRIN_SSEVEX_X_X_X_(paddq, SSE2, "paddq", INTRIN_COMMUTATIVE, A, B, C)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* @note goes fast w/ ssse3 (intel c. 2004, amd c. 2011)
|
||||
* @mayalias
|
||||
*/
|
||||
void(phaddd)(int32_t a[4], const int32_t b[4], const int32_t c[4]) {
|
||||
void(phaddd)(uint32_t a[4], const uint32_t b[4], const uint32_t c[4]) {
|
||||
int32_t t[4];
|
||||
t[0] = b[0] + b[1];
|
||||
t[1] = b[2] + b[3];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void phaddd(int32_t[4], const int32_t[4], const int32_t[4]);
|
||||
void phaddd(uint32_t[4], const uint32_t[4], const uint32_t[4]);
|
||||
|
||||
#define phaddd(A, B, C) \
|
||||
INTRIN_SSEVEX_X_X_X_(phaddd, SSSE3, "phaddd", INTRIN_NONCOMMUTATIVE, A, B, C)
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
* @note goes fast w/ ssse3
|
||||
* @mayalias
|
||||
*/
|
||||
void(phsubd)(int32_t a[4], const int32_t b[4], const int32_t c[4]) {
|
||||
int32_t t[4];
|
||||
void(phsubd)(uint32_t a[4], const uint32_t b[4], const uint32_t c[4]) {
|
||||
uint32_t t[4];
|
||||
t[0] = b[0] - b[1];
|
||||
t[1] = b[2] - b[3];
|
||||
t[2] = c[0] - c[1];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void phsubd(int32_t[4], const int32_t[4], const int32_t[4]);
|
||||
void phsubd(uint32_t[4], const uint32_t[4], const uint32_t[4]);
|
||||
|
||||
#define phsubd(A, B, C) \
|
||||
INTRIN_SSEVEX_X_X_X_(phsubd, SSSE3, "phsubd", INTRIN_NONCOMMUTATIVE, A, B, C)
|
||||
|
|
|
@ -29,9 +29,13 @@
|
|||
*/
|
||||
void(pmulhuw)(uint16_t a[8], const uint16_t b[8], const uint16_t c[8]) {
|
||||
unsigned i;
|
||||
uint32_t x;
|
||||
uint16_t r[8];
|
||||
for (i = 0; i < 8; ++i) {
|
||||
r[i] = ((b[i] * c[i]) & 0xffff0000) >> 16;
|
||||
x = b[i];
|
||||
x *= c[i];
|
||||
x >>= 16;
|
||||
r[i] = x;
|
||||
}
|
||||
memcpy(a, r, 16);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Multiplies 32-bit signed integers.
|
||||
* Multiplies 32-bit integers.
|
||||
*
|
||||
* @param 𝑎 [w/o] receives result
|
||||
* @param 𝑏 [r/o] supplies first input vector
|
||||
|
@ -28,9 +28,9 @@
|
|||
* @see pmuludq()
|
||||
* @mayalias
|
||||
*/
|
||||
void(pmulld)(int32_t a[4], const int32_t b[4], const int32_t c[4]) {
|
||||
void(pmulld)(uint32_t a[4], const uint32_t b[4], const uint32_t c[4]) {
|
||||
unsigned i;
|
||||
int32_t r[4];
|
||||
uint32_t r[4];
|
||||
for (i = 0; i < 4; ++i) {
|
||||
r[i] = b[i] * c[i];
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void pmulld(int32_t[4], const int32_t[4], const int32_t[4]);
|
||||
void pmulld(uint32_t[4], const uint32_t[4], const uint32_t[4]);
|
||||
|
||||
#define pmulld(A, B, C) \
|
||||
INTRIN_SSEVEX_X_X_X_(pmulld, SSE4_1, "pmulld", INTRIN_COMMUTATIVE, A, B, C)
|
||||
|
|
|
@ -29,7 +29,7 @@ void(psignd)(int32_t a[4], const int32_t b[4], const int32_t c[4]) {
|
|||
if (!c[i]) {
|
||||
a[i] = 0;
|
||||
} else if (c[i] < 0) {
|
||||
a[i] = -b[i];
|
||||
a[i] = -(uint32_t)b[i];
|
||||
} else {
|
||||
a[i] = b[i];
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
* @mayalias
|
||||
*/
|
||||
void(pslld)(uint32_t a[4], const uint32_t b[4], unsigned char c) {
|
||||
if (c <= 31) {
|
||||
unsigned i;
|
||||
if (c <= 31) {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
a[i] = b[i] << c;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Shifts vector right by n bytes w/ zero-fill.
|
||||
* Shifts vector left by n bytes w/ zero-fill.
|
||||
*
|
||||
* @param a is input vector
|
||||
* @param b receives output
|
||||
|
@ -28,7 +28,9 @@
|
|||
*/
|
||||
void(pslldq)(uint8_t b[16], const uint8_t a[16], unsigned long n) {
|
||||
unsigned i;
|
||||
uint8_t t[16];
|
||||
if (n > 16) n = 16;
|
||||
memmove(b + n, a, 16 - n);
|
||||
memset(b, 0, n);
|
||||
for (i = 0; i < n; ++i) t[i] = 0;
|
||||
for (i = 0; i < 16 - n; ++i) t[n + i] = a[i];
|
||||
memcpy(b, t, 16);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/psllw.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Multiplies shorts by two power.
|
||||
|
@ -25,13 +26,11 @@
|
|||
*/
|
||||
void(psllwv)(uint16_t a[8], const uint16_t b[8], const uint64_t c[2]) {
|
||||
unsigned i;
|
||||
if (c[0] > 15) {
|
||||
for (i = 0; i < 8; ++i) {
|
||||
a[i] = 0;
|
||||
}
|
||||
} else {
|
||||
if (c[0] < 16) {
|
||||
for (i = 0; i < 8; ++i) {
|
||||
a[i] = b[i] << c[0];
|
||||
}
|
||||
} else {
|
||||
memset(a, 0, 16);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,14 +26,9 @@
|
|||
* @mayalias
|
||||
*/
|
||||
void(psrad)(int32_t a[4], const int32_t b[4], unsigned char k) {
|
||||
unsigned i, x, m;
|
||||
unsigned i;
|
||||
if (k > 31) k = 31;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
m = 0;
|
||||
x = b[i];
|
||||
if (x & 0x80000000) m = ~(0xffffffffu >> k);
|
||||
x >>= k;
|
||||
x |= m;
|
||||
a[i] = x;
|
||||
a[i] = b[i] >> k;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,15 +25,10 @@
|
|||
* @mayalias
|
||||
*/
|
||||
void(psradv)(int32_t a[4], const int32_t b[4], const uint64_t c[2]) {
|
||||
unsigned i;
|
||||
unsigned char k;
|
||||
unsigned i, x, m;
|
||||
k = c[0] > 31 ? 31 : c[0];
|
||||
for (i = 0; i < 4; ++i) {
|
||||
m = 0;
|
||||
x = b[i];
|
||||
if (x & 0x80000000u) m = ~(0xffffffffu >> k);
|
||||
x >>= k;
|
||||
x |= m;
|
||||
a[i] = x & 0xffffffffu;
|
||||
a[i] = b[i] >> k;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,14 +26,9 @@
|
|||
* @mayalias
|
||||
*/
|
||||
void(psraw)(int16_t a[8], const int16_t b[8], unsigned char k) {
|
||||
unsigned i, x, m;
|
||||
unsigned i;
|
||||
if (k > 15) k = 15;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
m = 0;
|
||||
x = b[i];
|
||||
if (x & 0x8000) m = ~(0xffff >> k);
|
||||
x >>= k;
|
||||
x |= m;
|
||||
a[i] = x;
|
||||
a[i] = b[i] >> k;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,15 +25,10 @@
|
|||
* @mayalias
|
||||
*/
|
||||
void(psrawv)(int16_t a[8], const int16_t b[8], const uint64_t c[2]) {
|
||||
unsigned i;
|
||||
unsigned char k;
|
||||
unsigned i, x, m;
|
||||
k = c[0] > 15 ? 15 : c[0];
|
||||
for (i = 0; i < 8; ++i) {
|
||||
m = 0;
|
||||
x = b[i];
|
||||
if (x & 0x8000) m = ~(0xffffu >> k);
|
||||
x >>= k;
|
||||
x |= m;
|
||||
a[i] = x & 0xffffu;
|
||||
a[i] = b[i] >> k;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
* @param 𝑐 [r/o] supplies second input vector
|
||||
* @mayalias
|
||||
*/
|
||||
void(psubd)(int32_t a[4], const int32_t b[4], const int32_t c[4]) {
|
||||
void(psubd)(uint32_t a[4], const uint32_t b[4], const uint32_t c[4]) {
|
||||
unsigned i;
|
||||
int32_t r[4];
|
||||
uint32_t r[4];
|
||||
for (i = 0; i < 4; ++i) {
|
||||
r[i] = b[i] - c[i];
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void psubd(int32_t[4], const int32_t[4], const int32_t[4]);
|
||||
void psubd(uint32_t[4], const uint32_t[4], const uint32_t[4]);
|
||||
|
||||
#define psubd(A, B, C) \
|
||||
INTRIN_SSEVEX_X_X_X_(psubd, SSE2, "psubd", INTRIN_NONCOMMUTATIVE, A, B, C)
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
* @param 𝑐 [r/o] supplies second input vector
|
||||
* @mayalias
|
||||
*/
|
||||
void(psubq)(int64_t a[2], const int64_t b[2], const int64_t c[2]) {
|
||||
void(psubq)(uint64_t a[2], const uint64_t b[2], const uint64_t c[2]) {
|
||||
unsigned i;
|
||||
int64_t r[2];
|
||||
uint64_t r[2];
|
||||
for (i = 0; i < 2; ++i) {
|
||||
r[i] = b[i] - c[i];
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void psubq(int64_t[2], const int64_t[2], const int64_t[2]);
|
||||
void psubq(uint64_t[2], const uint64_t[2], const uint64_t[2]);
|
||||
|
||||
#define psubq(A, B, C) \
|
||||
INTRIN_SSEVEX_X_X_X_(psubq, SSE2, "psubq", INTRIN_NONCOMMUTATIVE, A, B, C)
|
||||
|
|
593
libc/intrin/ubsan.c
Normal file
593
libc/intrin/ubsan.c
Normal file
|
@ -0,0 +1,593 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/reverse.internal.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
#define kUbsanKindInt 0
|
||||
#define kUbsanKindFloat 1
|
||||
#define kUbsanKindUnknown 0xffff
|
||||
|
||||
struct UbsanSourceLocation {
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
};
|
||||
|
||||
struct UbsanTypeDescriptor {
|
||||
uint16_t kind; /* int,float,... */
|
||||
uint16_t info; /* if int bit 0 if signed, remaining bits are log2(sizeof*8) */
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct UbsanTypeMismatchInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
uintptr_t alignment;
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct UbsanTypeMismatchInfoClang {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
unsigned char log_alignment; /* https://reviews.llvm.org/D28244 */
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct UbsanOutOfBoundsInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *array_type;
|
||||
struct UbsanTypeDescriptor *index_type;
|
||||
};
|
||||
|
||||
struct UbsanUnreachableData {
|
||||
struct UbsanSourceLocation location;
|
||||
};
|
||||
|
||||
struct UbsanVlaBoundData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanNonnullArgData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanSourceLocation attr_location;
|
||||
};
|
||||
|
||||
struct UbsanCfiBadIcallData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanNonnullReturnData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanSourceLocation attr_location;
|
||||
};
|
||||
|
||||
struct UbsanFunctionTypeMismatchData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanInvalidValueData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanOverflowData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanFloatCastOverflowData {
|
||||
#if __GNUC__ + 0 >= 6
|
||||
struct UbsanSourceLocation location;
|
||||
#endif
|
||||
struct UbsanTypeDescriptor *from_type;
|
||||
struct UbsanTypeDescriptor *to_type;
|
||||
};
|
||||
|
||||
struct UbsanOutOfBoundsData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *arraytype;
|
||||
struct UbsanTypeDescriptor *index_type;
|
||||
};
|
||||
|
||||
struct UbsanShiftOutOfBoundsInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *lhs_type;
|
||||
struct UbsanTypeDescriptor *rhs_type;
|
||||
};
|
||||
|
||||
static const char kUbsanTypeCheckKinds[] = "\
|
||||
load of\0\
|
||||
store to\0\
|
||||
reference binding to\0\
|
||||
member access within\0\
|
||||
member call on\0\
|
||||
constructor call on\0\
|
||||
downcast of\0\
|
||||
downcast of\0\
|
||||
upcast of\0\
|
||||
cast to virtual base of\0\
|
||||
\0";
|
||||
|
||||
static int __ubsan_bits(struct UbsanTypeDescriptor *t) {
|
||||
return 1 << (t->info >> 1);
|
||||
}
|
||||
|
||||
static bool __ubsan_signed(struct UbsanTypeDescriptor *t) {
|
||||
return t->info & 1;
|
||||
}
|
||||
|
||||
static bool __ubsan_negative(struct UbsanTypeDescriptor *t, uintptr_t x) {
|
||||
return __ubsan_signed(t) && (intptr_t)x < 0;
|
||||
}
|
||||
|
||||
static size_t __ubsan_strlen(const char *s) {
|
||||
size_t n = 0;
|
||||
while (*s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static char *__ubsan_stpcpy(char *d, const char *s) {
|
||||
size_t i;
|
||||
for (i = 0;; ++i) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return d + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *__ubsan_poscpy(char *p, uintptr_t i) {
|
||||
int j = 0;
|
||||
do {
|
||||
p[j++] = i % 10 + '0';
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
reverse(p, j);
|
||||
return p + j;
|
||||
}
|
||||
|
||||
static char *__ubsan_intcpy(char *p, intptr_t i) {
|
||||
if (i >= 0) return __ubsan_poscpy(p, i);
|
||||
*p++ = '-';
|
||||
return __ubsan_poscpy(p, -i);
|
||||
}
|
||||
|
||||
static char *__ubsan_hexcpy(char *p, uintptr_t x, int k) {
|
||||
while (k) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *__ubsan_itpcpy(char *p, struct UbsanTypeDescriptor *t,
|
||||
uintptr_t x) {
|
||||
if (__ubsan_signed(t)) {
|
||||
return __ubsan_intcpy(p, x);
|
||||
} else {
|
||||
return __ubsan_poscpy(p, x);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *__ubsan_dubnul(const char *s, unsigned i) {
|
||||
size_t n;
|
||||
while (i--) {
|
||||
if ((n = __ubsan_strlen(s))) {
|
||||
s += n + 1;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static uintptr_t __ubsan_extend(struct UbsanTypeDescriptor *t, uintptr_t x) {
|
||||
int w;
|
||||
w = __ubsan_bits(t);
|
||||
if (w < sizeof(x) * CHAR_BIT) {
|
||||
x <<= sizeof(x) * CHAR_BIT - w;
|
||||
if (__ubsan_signed(t)) {
|
||||
x = (intptr_t)x >> w;
|
||||
} else {
|
||||
x >>= w;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static privileged noinline wontreturn void __ubsan_exit(int rc) {
|
||||
if (!IsWindows()) {
|
||||
asm volatile("syscall"
|
||||
: /* no outputs */
|
||||
: "a"(__NR_exit_group), "D"(rc)
|
||||
: "memory");
|
||||
unreachable;
|
||||
} else {
|
||||
ExitProcess(rc);
|
||||
}
|
||||
}
|
||||
|
||||
static privileged noinline ssize_t __ubsan_write(const void *data,
|
||||
size_t size) {
|
||||
ssize_t rc;
|
||||
uint32_t wrote;
|
||||
if (!IsWindows()) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(__NR_write), "D"(2), "S"(data), "d"(size)
|
||||
: "rcx", "r11", "memory");
|
||||
return rc;
|
||||
} else {
|
||||
if (WriteFile(GetStdHandle(kNtStdErrorHandle), data, size, &wrote, 0)) {
|
||||
return wrote;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t __ubsan_write_string(const char *s) {
|
||||
return __ubsan_write(s, __ubsan_strlen(s));
|
||||
}
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
char buf[1024], *p = buf;
|
||||
p = __ubsan_stpcpy(p, "error: ");
|
||||
p = __ubsan_stpcpy(p, loc->file), *p++ = ':';
|
||||
p = __ubsan_intcpy(p, loc->line);
|
||||
p = __ubsan_stpcpy(p, ": ");
|
||||
p = __ubsan_stpcpy(p, description);
|
||||
p = __ubsan_stpcpy(p, "\r\n");
|
||||
__ubsan_write_string(buf);
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
__ubsan_exit(134);
|
||||
}
|
||||
|
||||
static const char *__ubsan_describe_shift(
|
||||
struct UbsanShiftOutOfBoundsInfo *info, uintptr_t lhs, uintptr_t rhs) {
|
||||
if (__ubsan_negative(info->rhs_type, rhs)) {
|
||||
return "shift exponent is negative";
|
||||
} else if (rhs >= __ubsan_bits(info->lhs_type)) {
|
||||
return "shift exponent too large for type";
|
||||
} else if (__ubsan_negative(info->lhs_type, lhs)) {
|
||||
return "left shift of negative value";
|
||||
} else if (__ubsan_signed(info->lhs_type)) {
|
||||
return "signed left shift changed sign bit or overflowed";
|
||||
} else {
|
||||
return "wut shift out of bounds";
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
|
||||
uintptr_t lhs, uintptr_t rhs) {
|
||||
char buf[512], *p = buf;
|
||||
lhs = __ubsan_extend(info->lhs_type, lhs);
|
||||
rhs = __ubsan_extend(info->rhs_type, rhs);
|
||||
p = __ubsan_stpcpy(p, __ubsan_describe_shift(info, lhs, rhs)), *p++ = ' ';
|
||||
p = __ubsan_itpcpy(p, info->lhs_type, lhs), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->lhs_type->name), *p++ = ' ';
|
||||
p = __ubsan_itpcpy(p, info->rhs_type, rhs), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->rhs_type->name);
|
||||
__ubsan_abort(&info->location, buf);
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds_abort(
|
||||
struct UbsanShiftOutOfBoundsInfo *info, uintptr_t lhs, uintptr_t rhs) {
|
||||
__ubsan_handle_shift_out_of_bounds(info, lhs, rhs);
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
|
||||
uintptr_t index) {
|
||||
char buf[512], *p = buf;
|
||||
p = __ubsan_stpcpy(p, info->index_type->name);
|
||||
p = __ubsan_stpcpy(p, " index ");
|
||||
p = __ubsan_itpcpy(p, info->index_type, index);
|
||||
p = __ubsan_stpcpy(p, " into ");
|
||||
p = __ubsan_stpcpy(p, info->array_type->name);
|
||||
p = __ubsan_stpcpy(p, " out of bounds");
|
||||
__ubsan_abort(&info->location, buf);
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds_abort(struct UbsanOutOfBoundsInfo *info,
|
||||
uintptr_t index) {
|
||||
__ubsan_handle_out_of_bounds(info, index);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
|
||||
uintptr_t pointer) {
|
||||
const char *kind;
|
||||
char buf[512], *p = buf;
|
||||
if (!pointer) __ubsan_abort(&info->location, "null pointer access");
|
||||
kind = __ubsan_dubnul(kUbsanTypeCheckKinds, info->type_check_kind);
|
||||
if (info->alignment && (pointer & (info->alignment - 1))) {
|
||||
p = __ubsan_stpcpy(p, "unaligned ");
|
||||
p = __ubsan_stpcpy(p, kind), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->type->name), *p++ = ' ', *p++ = '@';
|
||||
p = __ubsan_itpcpy(p, info->type, pointer);
|
||||
p = __ubsan_stpcpy(p, " align ");
|
||||
p = __ubsan_intcpy(p, info->alignment);
|
||||
} else {
|
||||
p = __ubsan_stpcpy(p, "insufficient size\r\n\t");
|
||||
p = __ubsan_stpcpy(p, kind);
|
||||
p = __ubsan_stpcpy(p, " address 0x");
|
||||
p = __ubsan_hexcpy(p, pointer, sizeof(pointer) * CHAR_BIT);
|
||||
p = __ubsan_stpcpy(p, " with insufficient space for object of type ");
|
||||
p = __ubsan_stpcpy(p, info->type->name);
|
||||
}
|
||||
__ubsan_abort(&info->location, buf);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_abort(struct UbsanTypeMismatchInfo *info,
|
||||
uintptr_t pointer) {
|
||||
__ubsan_handle_type_mismatch(info, pointer);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(
|
||||
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
|
||||
struct UbsanTypeMismatchInfo mm;
|
||||
mm.location = type_mismatch->location;
|
||||
mm.type = type_mismatch->type;
|
||||
mm.alignment = 1u << type_mismatch->log_alignment;
|
||||
mm.type_check_kind = type_mismatch->type_check_kind;
|
||||
__ubsan_handle_type_mismatch(&mm, pointer);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1_abort(
|
||||
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
|
||||
__ubsan_handle_type_mismatch_v1(type_mismatch, pointer);
|
||||
}
|
||||
|
||||
void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw) {
|
||||
struct UbsanFloatCastOverflowData *data =
|
||||
(struct UbsanFloatCastOverflowData *)data_raw;
|
||||
#if __GNUC__ + 0 >= 6
|
||||
__ubsan_abort(&data->location, "float cast overflow");
|
||||
#else
|
||||
const struct UbsanSourceLocation kUnknownLocation = {
|
||||
"<unknown file>",
|
||||
pushpop(0),
|
||||
pushpop(0),
|
||||
};
|
||||
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow");
|
||||
#endif
|
||||
}
|
||||
|
||||
void __ubsan_handle_float_cast_overflow_abort(void *data_raw, void *from_raw) {
|
||||
__ubsan_handle_float_cast_overflow(data_raw, from_raw);
|
||||
}
|
||||
|
||||
void __ubsan_handle_add_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "add overflow");
|
||||
}
|
||||
|
||||
void __ubsan_handle_add_overflow_abort(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_add_overflow(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_alignment_assumption(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "alignment assumption");
|
||||
}
|
||||
|
||||
void __ubsan_handle_alignment_assumption_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_alignment_assumption(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "builtin unreachable");
|
||||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_builtin_unreachable(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_cfi_bad_type(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "cfi bad type");
|
||||
}
|
||||
|
||||
void __ubsan_handle_cfi_bad_type_abort(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_cfi_bad_type(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_cfi_check_fail(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "cfi check fail");
|
||||
}
|
||||
|
||||
void __ubsan_handle_cfi_check_fail_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_cfi_check_fail(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "divrem overflow");
|
||||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_divrem_overflow(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_dynamic_type_cache_miss(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "dynamic type cache miss");
|
||||
}
|
||||
|
||||
void __ubsan_handle_dynamic_type_cache_miss_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_dynamic_type_cache_miss(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_function_type_mismatch(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "function type mismatch");
|
||||
}
|
||||
|
||||
void __ubsan_handle_function_type_mismatch_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_function_type_mismatch(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_implicit_conversion(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "implicit conversion");
|
||||
}
|
||||
|
||||
void __ubsan_handle_implicit_conversion_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_implicit_conversion(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_invalid_builtin(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "invalid builtin");
|
||||
}
|
||||
|
||||
void __ubsan_handle_invalid_builtin_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_invalid_builtin(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "load invalid value (uninitialized? bool∌[01]?)");
|
||||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_load_invalid_value(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_missing_return(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "missing return");
|
||||
}
|
||||
|
||||
void __ubsan_handle_missing_return_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_missing_return(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "multiply overflow");
|
||||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow_abort(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_mul_overflow(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "negate overflow");
|
||||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_negate_overflow(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_arg(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nonnull argument");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_arg_abort(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_nonnull_arg(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return_v1(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "non-null return (v1)");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return_v1_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_nonnull_return_v1(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_nullability_arg(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nullability arg");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nullability_arg_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_nullability_arg(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_nullability_return_v1(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nullability return (v1)");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nullability_return_v1_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_nullability_return_v1(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "pointer overflow");
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_pointer_overflow(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_sub_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "subtract overflow");
|
||||
}
|
||||
|
||||
void __ubsan_handle_sub_overflow_abort(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_sub_overflow(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "vla bound not positive");
|
||||
}
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_vla_bound_not_positive(loc);
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nonnull return");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_nonnull_return(loc);
|
||||
}
|
||||
|
||||
void __ubsan_default_options(void) {
|
||||
}
|
||||
|
||||
void __ubsan_on_report(void) {
|
||||
}
|
||||
|
||||
void *__ubsan_get_current_report_data(void) {
|
||||
return 0;
|
||||
}
|
|
@ -29,10 +29,8 @@
|
|||
relegated wontreturn void __die(void) {
|
||||
static bool once;
|
||||
if (cmpxchg(&once, false, true)) {
|
||||
if (!IsTiny()) {
|
||||
if (IsDebuggerPresent(false)) DebugBreak();
|
||||
ShowBacktrace(2, NULL);
|
||||
}
|
||||
}
|
||||
exit(77);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/log/ubsan.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/signals.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -31,7 +30,6 @@
|
|||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
STATIC_YOINK("__die");
|
||||
STATIC_YOINK("__ubsan_abort");
|
||||
|
||||
extern const unsigned char __oncrash_thunks[7][11];
|
||||
|
||||
|
|
|
@ -1,528 +0,0 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.text.unlikely
|
||||
.source __FILE__
|
||||
|
||||
__ubsan_default_options:
|
||||
ret
|
||||
.endfn __ubsan_default_options
|
||||
|
||||
__ubsan_on_report:
|
||||
ret
|
||||
.endfn __ubsan_on_report,globl
|
||||
|
||||
__ubsan_get_current_report_data:
|
||||
xor %eax,%eax
|
||||
ret
|
||||
.endfn __ubsan_get_current_report_data,globl
|
||||
|
||||
__ubsan_handle_type_mismatch_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
call __ubsan_handle_type_mismatch
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_type_mismatch_abort,globl
|
||||
|
||||
__ubsan_handle_float_cast_overflow_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
call __ubsan_handle_float_cast_overflow
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_float_cast_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_type_mismatch_v1_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
call ___ubsan_handle_type_mismatch_v1
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_type_mismatch_v1_abort,globl
|
||||
|
||||
__ubsan_handle_type_mismatch_v1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
call ___ubsan_handle_type_mismatch_v1
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_type_mismatch_v1,globl
|
||||
|
||||
__ubsan_handle_add_overflow_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "add_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_add_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_add_overflow:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "add_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_add_overflow,globl
|
||||
|
||||
__ubsan_handle_alignment_assumption_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "alignment_assumption",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_alignment_assumption_abort,globl
|
||||
|
||||
__ubsan_handle_alignment_assumption:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "alignment_assumption",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_alignment_assumption,globl
|
||||
|
||||
__ubsan_handle_builtin_unreachable_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "builtin_unreachable",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_builtin_unreachable_abort,globl
|
||||
|
||||
__ubsan_handle_builtin_unreachable:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "builtin_unreachable",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_builtin_unreachable,globl
|
||||
|
||||
__ubsan_handle_cfi_bad_type_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "cfi_bad_type",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_cfi_bad_type_abort,globl
|
||||
|
||||
__ubsan_handle_cfi_bad_type:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "cfi_bad_type",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_cfi_bad_type,globl
|
||||
|
||||
__ubsan_handle_cfi_check_fail_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "cfi_check_fail",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_cfi_check_fail_abort,globl
|
||||
|
||||
__ubsan_handle_cfi_check_fail:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "cfi_check_fail",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_cfi_check_fail,globl
|
||||
|
||||
__ubsan_handle_divrem_overflow_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "divrem_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_divrem_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_divrem_overflow:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "divrem_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_divrem_overflow,globl
|
||||
|
||||
__ubsan_handle_dynamic_type_cache_miss_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "dynamic_type_cache_miss",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_dynamic_type_cache_miss_abort,globl
|
||||
|
||||
__ubsan_handle_dynamic_type_cache_miss:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "dynamic_type_cache_miss",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_dynamic_type_cache_miss,globl
|
||||
|
||||
__ubsan_handle_function_type_mismatch_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "function_type_mismatch",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_function_type_mismatch_abort,globl
|
||||
|
||||
__ubsan_handle_function_type_mismatch:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "function_type_mismatch",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_function_type_mismatch,globl
|
||||
|
||||
__ubsan_handle_implicit_conversion_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "implicit_conversion",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_implicit_conversion_abort,globl
|
||||
|
||||
__ubsan_handle_implicit_conversion:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "implicit_conversion",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_implicit_conversion,globl
|
||||
|
||||
__ubsan_handle_invalid_builtin_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "invalid_builtin",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_invalid_builtin_abort,globl
|
||||
|
||||
__ubsan_handle_invalid_builtin:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "invalid_builtin",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_invalid_builtin,globl
|
||||
|
||||
__ubsan_handle_load_invalid_value_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "load_invalid_value (uninitialized? bool∌[01]?)",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_load_invalid_value_abort,globl
|
||||
|
||||
__ubsan_handle_load_invalid_value:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "load_invalid_value (uninitialized? bool∌[01]?)",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_load_invalid_value,globl
|
||||
|
||||
__ubsan_handle_missing_return_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "missing_return",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_missing_return_abort,globl
|
||||
|
||||
__ubsan_handle_missing_return:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "missing_return",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_missing_return,globl
|
||||
|
||||
__ubsan_handle_mul_overflow_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "mul_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_mul_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_mul_overflow:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "mul_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_mul_overflow,globl
|
||||
|
||||
__ubsan_handle_negate_overflow_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "negate_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_negate_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_negate_overflow:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "negate_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_negate_overflow,globl
|
||||
|
||||
__ubsan_handle_nonnull_arg_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nonnull_arg",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nonnull_arg_abort,globl
|
||||
|
||||
__ubsan_handle_nonnull_arg:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nonnull_arg",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nonnull_arg,globl
|
||||
|
||||
__ubsan_handle_nonnull_return_v1_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nonnull_return_v1",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nonnull_return_v1_abort,globl
|
||||
|
||||
__ubsan_handle_nonnull_return_v1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nonnull_return_v1",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nonnull_return_v1,globl
|
||||
|
||||
__ubsan_handle_nullability_arg_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nullability_arg",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nullability_arg_abort,globl
|
||||
|
||||
__ubsan_handle_nullability_arg:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nullability_arg",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nullability_arg,globl
|
||||
|
||||
__ubsan_handle_nullability_return_v1_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nullability_return_v1",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nullability_return_v1_abort,globl
|
||||
|
||||
__ubsan_handle_nullability_return_v1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nullability_return_v1",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nullability_return_v1,globl
|
||||
|
||||
__ubsan_handle_pointer_overflow_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "pointer_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_pointer_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_pointer_overflow:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "pointer_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_pointer_overflow,globl
|
||||
|
||||
__ubsan_handle_shift_out_of_bounds_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
call __ubsan_handle_shift_out_of_bounds
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_shift_out_of_bounds_abort,globl
|
||||
|
||||
__ubsan_handle_sub_overflow_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "sub_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_sub_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_sub_overflow:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "sub_overflow",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_sub_overflow,globl
|
||||
|
||||
__ubsan_handle_vla_bound_not_positive_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "vla_bound_not_positive",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_vla_bound_not_positive_abort,globl
|
||||
|
||||
__ubsan_handle_vla_bound_not_positive:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "vla_bound_not_positive",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_vla_bound_not_positive,globl
|
||||
|
||||
__ubsan_handle_nonnull_return_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nonnull_return",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nonnull_return_abort,globl
|
||||
|
||||
__ubsan_handle_nonnull_return:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
loadstr "nonnull_return",si
|
||||
call __ubsan_abort
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_nonnull_return,globl
|
||||
|
||||
__ubsan_handle_out_of_bounds_abort:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
call __ubsan_handle_out_of_bounds
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __ubsan_handle_out_of_bounds_abort,globl
|
232
libc/log/ubsan.c
232
libc/log/ubsan.c
|
@ -1,232 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/reverse.internal.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/log/ubsan.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
static char __ubsan_buf[256];
|
||||
|
||||
static const char kUbsanTypeCheckKinds[] = "\
|
||||
load of\0\
|
||||
store to\0\
|
||||
reference binding to\0\
|
||||
member access within\0\
|
||||
member call on\0\
|
||||
constructor call on\0\
|
||||
downcast of\0\
|
||||
downcast of\0\
|
||||
upcast of\0\
|
||||
cast to virtual base of\0\
|
||||
\0";
|
||||
|
||||
static int __ubsan_bits(struct UbsanTypeDescriptor *t) {
|
||||
return 1 << (t->info >> 1);
|
||||
}
|
||||
|
||||
static bool __ubsan_signed(struct UbsanTypeDescriptor *t) {
|
||||
return t->info & 1;
|
||||
}
|
||||
|
||||
static bool __ubsan_negative(struct UbsanTypeDescriptor *t, uintptr_t x) {
|
||||
return __ubsan_signed(t) && (intptr_t)x < 0;
|
||||
}
|
||||
|
||||
static size_t __ubsan_strlen(const char *s) {
|
||||
size_t n = 0;
|
||||
while (*s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static char *__ubsan_stpcpy(char *d, const char *s) {
|
||||
size_t i;
|
||||
for (i = 0;; ++i) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return d + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *__ubsan_poscpy(char *p, uintptr_t i) {
|
||||
int j = 0;
|
||||
do {
|
||||
p[j++] = i % 10 + '0';
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
reverse(p, j);
|
||||
return p + j;
|
||||
}
|
||||
|
||||
static char *__ubsan_intcpy(char *p, intptr_t i) {
|
||||
if (i >= 0) return __ubsan_poscpy(p, i);
|
||||
*p++ = '-';
|
||||
return __ubsan_poscpy(p, -i);
|
||||
}
|
||||
|
||||
static char *__ubsan_hexcpy(char *p, uintptr_t x, int k) {
|
||||
while (k) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *__ubsan_itpcpy(char *p, struct UbsanTypeDescriptor *t,
|
||||
uintptr_t x) {
|
||||
if (__ubsan_signed(t)) {
|
||||
return __ubsan_intcpy(p, x);
|
||||
} else {
|
||||
return __ubsan_poscpy(p, x);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *__ubsan_dubnul(const char *s, unsigned i) {
|
||||
size_t n;
|
||||
while (i--) {
|
||||
if ((n = __ubsan_strlen(s))) {
|
||||
s += n + 1;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static uintptr_t __ubsan_extend(struct UbsanTypeDescriptor *t, uintptr_t x) {
|
||||
int w;
|
||||
w = __ubsan_bits(t);
|
||||
if (w < sizeof(x) * CHAR_BIT) {
|
||||
x <<= sizeof(x) * CHAR_BIT - w;
|
||||
if (__ubsan_signed(t)) {
|
||||
x = (intptr_t)x >> w;
|
||||
} else {
|
||||
x >>= w;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
static bool once;
|
||||
if (!once) {
|
||||
once = true;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
if (IsDebuggerPresent(false)) DebugBreak();
|
||||
__start_fatal(loc->file, loc->line);
|
||||
write(2, description, strlen(description));
|
||||
write(2, "\r\n", 2);
|
||||
__die();
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
|
||||
uintptr_t lhs, uintptr_t rhs) {
|
||||
char *p;
|
||||
const char *s;
|
||||
lhs = __ubsan_extend(info->lhs_type, lhs);
|
||||
rhs = __ubsan_extend(info->rhs_type, rhs);
|
||||
if (__ubsan_negative(info->rhs_type, rhs)) {
|
||||
s = "shift exponent is negative";
|
||||
} else if (rhs >= __ubsan_bits(info->lhs_type)) {
|
||||
s = "shift exponent too large for type";
|
||||
} else if (__ubsan_negative(info->lhs_type, lhs)) {
|
||||
s = "left shift of negative value";
|
||||
} else if (__ubsan_signed(info->lhs_type)) {
|
||||
s = "signed left shift changed sign bit or overflowed";
|
||||
} else {
|
||||
s = "wut shift out of bounds";
|
||||
}
|
||||
p = __ubsan_buf;
|
||||
p = __ubsan_stpcpy(p, s), *p++ = ' ';
|
||||
p = __ubsan_itpcpy(p, info->lhs_type, lhs), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->lhs_type->name), *p++ = ' ';
|
||||
p = __ubsan_itpcpy(p, info->rhs_type, rhs), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->rhs_type->name);
|
||||
__ubsan_abort(&info->location, __ubsan_buf);
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
|
||||
uintptr_t index) {
|
||||
char *p;
|
||||
p = __ubsan_buf;
|
||||
p = __ubsan_stpcpy(p, info->index_type->name);
|
||||
p = __ubsan_stpcpy(p, " index ");
|
||||
p = __ubsan_itpcpy(p, info->index_type, index);
|
||||
p = __ubsan_stpcpy(p, " into ");
|
||||
p = __ubsan_stpcpy(p, info->array_type->name);
|
||||
p = __ubsan_stpcpy(p, " out of bounds");
|
||||
__ubsan_abort(&info->location, __ubsan_buf);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
|
||||
uintptr_t pointer) {
|
||||
char *p;
|
||||
const char *kind;
|
||||
if (!pointer) __ubsan_abort(&info->location, "null pointer access");
|
||||
p = __ubsan_buf;
|
||||
kind = __ubsan_dubnul(kUbsanTypeCheckKinds, info->type_check_kind);
|
||||
if (info->alignment && (pointer & (info->alignment - 1))) {
|
||||
p = __ubsan_stpcpy(p, "unaligned ");
|
||||
p = __ubsan_stpcpy(p, kind), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->type->name), *p++ = ' ', *p++ = '@';
|
||||
p = __ubsan_itpcpy(p, info->type, pointer);
|
||||
p = __ubsan_stpcpy(p, " align ");
|
||||
p = __ubsan_intcpy(p, info->alignment);
|
||||
} else {
|
||||
p = __ubsan_stpcpy(p, "insufficient size\r\n\t");
|
||||
p = __ubsan_stpcpy(p, kind);
|
||||
p = __ubsan_stpcpy(p, " address 0x");
|
||||
p = __ubsan_hexcpy(p, pointer, sizeof(pointer) * CHAR_BIT);
|
||||
p = __ubsan_stpcpy(p, " with insufficient space for object of type ");
|
||||
p = __ubsan_stpcpy(p, info->type->name);
|
||||
}
|
||||
__ubsan_abort(&info->location, __ubsan_buf);
|
||||
}
|
||||
|
||||
void ___ubsan_handle_type_mismatch_v1(
|
||||
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
|
||||
struct UbsanTypeMismatchInfo mm;
|
||||
mm.location = type_mismatch->location;
|
||||
mm.type = type_mismatch->type;
|
||||
mm.alignment = 1u << type_mismatch->log_alignment;
|
||||
mm.type_check_kind = type_mismatch->type_check_kind;
|
||||
__ubsan_handle_type_mismatch(&mm, pointer);
|
||||
}
|
||||
|
||||
void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw) {
|
||||
struct UbsanFloatCastOverflowData *data =
|
||||
(struct UbsanFloatCastOverflowData *)data_raw;
|
||||
#if __GNUC__ + 0 >= 6
|
||||
__ubsan_abort(&data->location, "float cast overflow");
|
||||
#else
|
||||
const struct UbsanSourceLocation kUnknownLocation = {
|
||||
"<unknown file>",
|
||||
pushpop(0),
|
||||
pushpop(0),
|
||||
};
|
||||
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow");
|
||||
#endif
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_UBSAN_H_
|
||||
#define COSMOPOLITAN_LIBC_UBSAN_H_
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § runtime » behavior enforcement ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define kUbsanKindInt 0
|
||||
#define kUbsanKindFloat 1
|
||||
#define kUbsanKindUnknown 0xffff
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
struct UbsanSourceLocation {
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
};
|
||||
|
||||
struct UbsanTypeDescriptor {
|
||||
uint16_t kind; /* int,float,... */
|
||||
uint16_t info; /* if int bit 0 if signed, remaining bits are log2(sizeof*8) */
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct UbsanTypeMismatchInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
uintptr_t alignment;
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct UbsanTypeMismatchInfoClang {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
unsigned char log_alignment; /* https://reviews.llvm.org/D28244 */
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct UbsanOutOfBoundsInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *array_type;
|
||||
struct UbsanTypeDescriptor *index_type;
|
||||
};
|
||||
|
||||
struct UbsanUnreachableData {
|
||||
struct UbsanSourceLocation location;
|
||||
};
|
||||
|
||||
struct UbsanVlaBoundData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanNonnullArgData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanSourceLocation attr_location;
|
||||
};
|
||||
|
||||
struct UbsanCfiBadIcallData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanNonnullReturnData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanSourceLocation attr_location;
|
||||
};
|
||||
|
||||
struct UbsanFunctionTypeMismatchData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanInvalidValueData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanOverflowData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanFloatCastOverflowData {
|
||||
#if __GNUC__ + 0 >= 6
|
||||
struct UbsanSourceLocation location;
|
||||
#endif
|
||||
struct UbsanTypeDescriptor *from_type;
|
||||
struct UbsanTypeDescriptor *to_type;
|
||||
};
|
||||
|
||||
struct UbsanOutOfBoundsData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *arraytype;
|
||||
struct UbsanTypeDescriptor *index_type;
|
||||
};
|
||||
|
||||
struct UbsanShiftOutOfBoundsInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *lhs_type;
|
||||
struct UbsanTypeDescriptor *rhs_type;
|
||||
};
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *,
|
||||
const char *) relegated hidden wontreturn;
|
||||
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *,
|
||||
uintptr_t) relegated hidden wontreturn;
|
||||
void ___ubsan_handle_type_mismatch_v1(struct UbsanTypeMismatchInfoClang *,
|
||||
uintptr_t) relegated hidden wontreturn;
|
||||
void __ubsan_handle_float_cast_overflow(void *,
|
||||
void *) relegated hidden wontreturn;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_UBSAN_H_ */
|
|
@ -62,7 +62,7 @@ void *memccpy(void *dst, const void *src, int c, size_t n) {
|
|||
d = dst;
|
||||
s = src;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
v = 0x0101010101010101ul * c;
|
||||
for (; (uintptr_t)(s + i) & 7; ++i) {
|
||||
if (i == n) return NULL;
|
||||
if ((d[i] = s[i]) == c) return d + i + 1;
|
||||
|
|
|
@ -31,7 +31,7 @@ void *memchr(const void *m, int c, size_t n) {
|
|||
uint64_t v, w;
|
||||
const char *p, *pe;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
v = 0x0101010101010101ul * c;
|
||||
for (p = m, pe = p + n; p + 8 <= pe; p += 8) {
|
||||
w = (uint64_t)(255 & p[7]) << 070 | (uint64_t)(255 & p[6]) << 060 |
|
||||
(uint64_t)(255 & p[5]) << 050 | (uint64_t)(255 & p[4]) << 040 |
|
||||
|
|
|
@ -31,7 +31,7 @@ void *memset_pure(void *p, int c, size_t n) {
|
|||
char *b;
|
||||
uint64_t x;
|
||||
b = p;
|
||||
x = 0x0101010101010101 * (c & 0xff);
|
||||
x = 0x0101010101010101ul * (c & 0xff);
|
||||
switch (n) {
|
||||
case 0:
|
||||
return p;
|
||||
|
|
|
@ -37,7 +37,7 @@ void *rawmemchr(const void *m, int c) {
|
|||
const unsigned char *s;
|
||||
s = m;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
v = 0x0101010101010101ul * c;
|
||||
for (; (uintptr_t)s & 7; ++s) {
|
||||
if (*s == c) return s;
|
||||
}
|
||||
|
|
|
@ -1,311 +0,0 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/macros.internal.h"
|
||||
.real
|
||||
.code16 # ∩ .code32 ∩ .code64
|
||||
.source __FILE__
|
||||
|
||||
/**
|
||||
* @fileoverview Overridable stubs for synthetic sanitizer calls.
|
||||
*/
|
||||
|
||||
__ubsan_default_options:
|
||||
ret
|
||||
.endfn __ubsan_default_options,weak
|
||||
|
||||
__ubsan_get_current_report_data:
|
||||
ret
|
||||
.endfn __ubsan_get_current_report_data,weak
|
||||
|
||||
__ubsan_handle_add_overflow:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_add_overflow,weak
|
||||
|
||||
__ubsan_handle_add_overflow_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_add_overflow_abort,weak
|
||||
|
||||
__ubsan_handle_alignment_assumption:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_alignment_assumption,weak
|
||||
|
||||
__ubsan_handle_alignment_assumption_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_alignment_assumption_abort,weak
|
||||
|
||||
__ubsan_handle_builtin_unreachable:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_builtin_unreachable,weak
|
||||
|
||||
__ubsan_handle_builtin_unreachable_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_builtin_unreachable_abort,weak
|
||||
|
||||
__ubsan_handle_cfi_bad_type:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_cfi_bad_type,weak
|
||||
|
||||
__ubsan_handle_cfi_bad_type_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_cfi_bad_type_abort,weak
|
||||
|
||||
__ubsan_handle_cfi_check_fail:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_cfi_check_fail,weak
|
||||
|
||||
__ubsan_handle_cfi_check_fail_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_cfi_check_fail_abort,weak
|
||||
|
||||
__ubsan_handle_divrem_overflow:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_divrem_overflow,weak
|
||||
|
||||
__ubsan_handle_divrem_overflow_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_divrem_overflow_abort,weak
|
||||
|
||||
__ubsan_handle_dynamic_type_cache_miss:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_dynamic_type_cache_miss,weak
|
||||
|
||||
__ubsan_handle_dynamic_type_cache_miss_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_dynamic_type_cache_miss_abort,weak
|
||||
|
||||
__ubsan_handle_float_cast_overflow:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_float_cast_overflow,weak
|
||||
|
||||
__ubsan_handle_float_cast_overflow_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_float_cast_overflow_abort,weak
|
||||
|
||||
__ubsan_handle_function_type_mismatch:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_function_type_mismatch,weak
|
||||
|
||||
__ubsan_handle_function_type_mismatch_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_function_type_mismatch_abort,weak
|
||||
|
||||
__ubsan_handle_implicit_conversion:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_implicit_conversion,weak
|
||||
|
||||
__ubsan_handle_implicit_conversion_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_implicit_conversion_abort,weak
|
||||
|
||||
__ubsan_handle_invalid_builtin:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_invalid_builtin,weak
|
||||
|
||||
__ubsan_handle_invalid_builtin_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_invalid_builtin_abort,weak
|
||||
|
||||
__ubsan_handle_load_invalid_value:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_load_invalid_value,weak
|
||||
|
||||
__ubsan_handle_load_invalid_value_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_load_invalid_value_abort,weak
|
||||
|
||||
__ubsan_handle_missing_return:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_missing_return,weak
|
||||
|
||||
__ubsan_handle_missing_return_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_missing_return_abort,weak
|
||||
|
||||
__ubsan_handle_mul_overflow:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_mul_overflow,weak
|
||||
|
||||
__ubsan_handle_mul_overflow_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_mul_overflow_abort,weak
|
||||
|
||||
__ubsan_handle_negate_overflow:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_negate_overflow,weak
|
||||
|
||||
__ubsan_handle_negate_overflow_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_negate_overflow_abort,weak
|
||||
|
||||
__ubsan_handle_nonnull_arg:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nonnull_arg,weak
|
||||
|
||||
__ubsan_handle_nonnull_arg_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nonnull_arg_abort,weak
|
||||
|
||||
__ubsan_handle_nonnull_return:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nonnull_return,weak
|
||||
|
||||
__ubsan_handle_nonnull_return_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nonnull_return_abort,weak
|
||||
|
||||
__ubsan_handle_nonnull_return_v1:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nonnull_return_v1,weak
|
||||
|
||||
__ubsan_handle_nonnull_return_v1_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nonnull_return_v1_abort,weak
|
||||
|
||||
__ubsan_handle_nullability_arg:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nullability_arg,weak
|
||||
|
||||
__ubsan_handle_nullability_arg_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nullability_arg_abort,weak
|
||||
|
||||
__ubsan_handle_nullability_return_v1:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nullability_return_v1,weak
|
||||
|
||||
__ubsan_handle_nullability_return_v1_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_nullability_return_v1_abort,weak
|
||||
|
||||
__ubsan_handle_out_of_bounds:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_out_of_bounds,weak
|
||||
|
||||
__ubsan_handle_out_of_bounds_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_out_of_bounds_abort,weak
|
||||
|
||||
__ubsan_handle_pointer_overflow:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_pointer_overflow,weak
|
||||
|
||||
__ubsan_handle_pointer_overflow_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_pointer_overflow_abort,weak
|
||||
|
||||
__ubsan_handle_shift_out_of_bounds:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_shift_out_of_bounds,weak
|
||||
|
||||
__ubsan_handle_shift_out_of_bounds_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_shift_out_of_bounds_abort,weak
|
||||
|
||||
__ubsan_handle_sub_overflow:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_sub_overflow,weak
|
||||
|
||||
__ubsan_handle_sub_overflow_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_sub_overflow_abort,weak
|
||||
|
||||
__ubsan_handle_type_mismatch:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_type_mismatch,weak
|
||||
|
||||
__ubsan_handle_type_mismatch_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_type_mismatch_abort,weak
|
||||
|
||||
__ubsan_handle_type_mismatch_v1:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_type_mismatch_v1,weak
|
||||
|
||||
__ubsan_handle_type_mismatch_v1_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_type_mismatch_v1_abort,weak
|
||||
|
||||
__ubsan_handle_vla_bound_not_positive:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_vla_bound_not_positive,weak
|
||||
|
||||
__ubsan_handle_vla_bound_not_positive_abort:
|
||||
nop
|
||||
// fallthrough
|
||||
.endfn __ubsan_handle_vla_bound_not_positive_abort,weak
|
||||
|
||||
__ubsan_abort_stub:
|
||||
push %bp
|
||||
mov %sp,%bp
|
||||
1: int3
|
||||
jmp 1b
|
||||
.endfn __ubsan_abort_stub
|
|
@ -103,10 +103,14 @@ void OnFpe(int sig, struct siginfo *si, struct ucontext *ctx) {
|
|||
ctx->uc_mcontext.rdx = 0;
|
||||
}
|
||||
|
||||
TEST(sigaction, sigFpe_handlerCanEditProcessStateAndRecoverExecution) {
|
||||
noubsan void ubsanTrumpsSystemsEngineering(void) {
|
||||
struct sigaction saint = {.sa_sigaction = OnFpe, .sa_flags = SA_SIGINFO};
|
||||
EXPECT_NE(-1, sigaction(SIGFPE, &saint, &oldsa));
|
||||
volatile long x = 0;
|
||||
EXPECT_EQ(42, 666 / x); /* systems engineering trumps math */
|
||||
EXPECT_NE(-1, sigaction(SIGFPE, &oldsa, NULL));
|
||||
}
|
||||
|
||||
TEST(sigaction, sigFpe_handlerCanEditProcessStateAndRecoverExecution) {
|
||||
ubsanTrumpsSystemsEngineering();
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
#include "libc/intrin/psrlq.h"
|
||||
#include "libc/intrin/psrlw.h"
|
||||
#include "libc/intrin/psubb.h"
|
||||
#include "libc/intrin/psubd.h"
|
||||
#include "libc/intrin/psubq.h"
|
||||
#include "libc/intrin/psubsb.h"
|
||||
#include "libc/intrin/psubsw.h"
|
||||
|
@ -581,7 +582,7 @@ TEST(punpckhbw, fuzz) {
|
|||
|
||||
TEST(psubq, fuzz) {
|
||||
int i, j;
|
||||
int64_t x[2], y[2], a[2], b[2];
|
||||
uint64_t x[2], y[2], a[2], b[2];
|
||||
for (i = 0; i < 100; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
RngSet(y, sizeof(y));
|
||||
|
@ -660,7 +661,7 @@ TEST(psradv, test) {
|
|||
for (i = 0; i < 100; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
for (j = 0; j < 2; ++j) {
|
||||
y[j] = Rando() % 64;
|
||||
y[j] = Rando() % 70;
|
||||
}
|
||||
psradv(a, x, y);
|
||||
(psradv)(b, x, y);
|
||||
|
@ -843,7 +844,7 @@ TEST(pmullw, fuzz) {
|
|||
|
||||
TEST(pmulld, fuzz) {
|
||||
int i, j;
|
||||
int32_t x[4], y[4], a[4], b[4];
|
||||
uint32_t x[4], y[4], a[4], b[4];
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
RngSet(y, sizeof(y));
|
||||
|
@ -906,8 +907,8 @@ TEST(phaddw, fuzz) {
|
|||
|
||||
TEST(phaddd, fuzz) {
|
||||
int i, j;
|
||||
int32_t x[4], y[4];
|
||||
int32_t a[4], b[4];
|
||||
uint32_t x[4], y[4];
|
||||
uint32_t a[4], b[4];
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
RngSet(y, sizeof(y));
|
||||
|
@ -938,8 +939,8 @@ TEST(phsubw, fuzz) {
|
|||
|
||||
TEST(phsubd, fuzz) {
|
||||
int i, j;
|
||||
int32_t x[4], y[4];
|
||||
int32_t a[4], b[4];
|
||||
uint32_t x[4], y[4];
|
||||
uint32_t a[4], b[4];
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
RngSet(y, sizeof(y));
|
||||
|
@ -952,6 +953,22 @@ TEST(phsubd, fuzz) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(psubd, fuzz) {
|
||||
int i, j;
|
||||
uint32_t x[4], y[4];
|
||||
uint32_t a[4], b[4];
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
RngSet(y, sizeof(y));
|
||||
psubd(a, x, y);
|
||||
(psubd)(b, x, y);
|
||||
ASSERT_EQ(0, memcmp(a, b, 16));
|
||||
psubd(a, (void *)a, y);
|
||||
(psubd)(b, (void *)b, y);
|
||||
ASSERT_EQ(0, memcmp(a, b, 16));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(phaddsw, fuzz) {
|
||||
int i, j;
|
||||
int16_t x[8], y[8];
|
||||
|
@ -1157,7 +1174,7 @@ TEST(pandn, fuzz) {
|
|||
|
||||
TEST(paddq, fuzz) {
|
||||
int i, j;
|
||||
int64_t x[2], y[2], a[2], b[2];
|
||||
uint64_t x[2], y[2], a[2], b[2];
|
||||
for (i = 0; i < 100; ++i) {
|
||||
for (j = 0; j < 2; ++j) x[j] = Rando();
|
||||
for (j = 0; j < 2; ++j) y[j] = Rando();
|
||||
|
@ -1444,6 +1461,12 @@ TEST(pabsd, fuzz) {
|
|||
int i, j;
|
||||
int32_t x[4];
|
||||
uint32_t a[4], b[4];
|
||||
x[0] = INT_MIN;
|
||||
pabsd((uint32_t *)x, x);
|
||||
EXPECT_EQ(INT_MIN, x[0]);
|
||||
x[0] = INT_MIN;
|
||||
(pabsd)((uint32_t *)x, x);
|
||||
EXPECT_EQ(INT_MIN, x[0]);
|
||||
for (i = 0; i < 100; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
pabsd(a, x);
|
||||
|
@ -1497,6 +1520,16 @@ TEST(psignd, fuzz) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(psignd, testBane) {
|
||||
int32_t x[4] = {INT_MIN, INT_MIN, INT_MIN, INT_MIN};
|
||||
int32_t y[4] = {0, 1, -1, INT_MIN};
|
||||
psignd(x, x, y);
|
||||
EXPECT_EQ(0, x[0]);
|
||||
EXPECT_EQ(INT_MIN, x[1]);
|
||||
EXPECT_EQ(INT_MIN, x[2]);
|
||||
EXPECT_EQ(INT_MIN, x[3]);
|
||||
}
|
||||
|
||||
TEST(paddb, fuzz) {
|
||||
int i, j;
|
||||
int8_t x[16], y[16], a[16], b[16];
|
||||
|
@ -1574,7 +1607,12 @@ TEST(psubsw, fuzz) {
|
|||
|
||||
TEST(paddd, fuzz) {
|
||||
int i, j;
|
||||
int32_t x[4], y[4], a[4], b[4];
|
||||
uint32_t x[4], y[4], a[4], b[4];
|
||||
RngSet(x, sizeof(x));
|
||||
RngSet(y, sizeof(y));
|
||||
x[0] = 0x7fffffff;
|
||||
y[0] = 0x7fffffff;
|
||||
(paddd)(b, x, y);
|
||||
for (i = 0; i < 100; ++i) {
|
||||
RngSet(x, sizeof(x));
|
||||
RngSet(y, sizeof(y));
|
||||
|
|
|
@ -78,6 +78,13 @@ TEST(pmulhrsw, testLimits) {
|
|||
EXPECT_EQ(kPmulhrswTorture[i][2], A[0], "pmulhrsw(%hd,%hd)→%hd",
|
||||
kPmulhrswTorture[i][0], kPmulhrswTorture[i][1], A[0]);
|
||||
}
|
||||
for (i = 0; i < ARRAYLEN(kPmulhrswTorture); ++i) {
|
||||
A[0] = kPmulhrswTorture[i][0];
|
||||
B[0] = kPmulhrswTorture[i][1];
|
||||
(pmulhrsw)(A, A, B);
|
||||
EXPECT_EQ(kPmulhrswTorture[i][2], A[0], "pmulhrsw(%hd,%hd)→%hd",
|
||||
kPmulhrswTorture[i][0], kPmulhrswTorture[i][1], A[0]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(pmulhrsw, testFakeFloat) {
|
||||
|
|
4
third_party/gdtoa/g_xfmt.c
vendored
4
third_party/gdtoa/g_xfmt.c
vendored
|
@ -73,8 +73,8 @@ g_xfmt(char *buf, void *V, int ndig, size_t bufsize)
|
|||
|
||||
L = (UShort *)V;
|
||||
sign = L[_0] & 0x8000;
|
||||
bits[1] = (L[_1] << 16) | L[_2];
|
||||
bits[0] = (L[_3] << 16) | L[_4];
|
||||
bits[1] = ((ULong)L[_1] << 16) | L[_2];
|
||||
bits[0] = ((ULong)L[_3] << 16) | L[_4];
|
||||
if ( (ex = L[_0] & 0x7fff) !=0) {
|
||||
if (ex == 0x7fff) {
|
||||
/* Infinity or NaN */
|
||||
|
|
4
third_party/gdtoa/g_xfmt_p.c
vendored
4
third_party/gdtoa/g_xfmt_p.c
vendored
|
@ -75,8 +75,8 @@ g_xfmt_p(char *buf, void *V, int ndig, size_t bufsize, int nik)
|
|||
|
||||
L = (UShort *)V;
|
||||
sign = L[_0] & 0x8000;
|
||||
bits[1] = (L[_1] << 16) | L[_2];
|
||||
bits[0] = (L[_3] << 16) | L[_4];
|
||||
bits[1] = ((ULong)L[_1] << 16) | L[_2];
|
||||
bits[0] = ((ULong)L[_3] << 16) | L[_4];
|
||||
if ( (ex = L[_0] & 0x7fff) !=0) {
|
||||
if (ex == 0x7fff) {
|
||||
/* Infinity or NaN */
|
||||
|
|
18
third_party/gdtoa/gdtoa.c
vendored
18
third_party/gdtoa/gdtoa.c
vendored
|
@ -241,7 +241,23 @@ gdtoa(CONST FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, in
|
|||
dval(&d) *= 1 << j1;
|
||||
word0(&d) += j << Exp_shift - 2 & Exp_mask;
|
||||
#else
|
||||
word0(&d) += (be + bbits - 1) << Exp_shift;
|
||||
// TODO: word0(&d) += (be + bbits - 1) << Exp_shift;
|
||||
// error: third_party/gdtoa/gdtoa.c:244: left shift of negative value -6 'int' 20 'int'
|
||||
// 4161d8: __die at libc/log/die.c:33
|
||||
// 463165: __ubsan_abort at libc/intrin/ubsan.c:270
|
||||
// 4632d6: __ubsan_handle_shift_out_of_bounds at libc/intrin/ubsan.c:299
|
||||
// 421d42: gdtoa at third_party/gdtoa/gdtoa.c:244
|
||||
// 420449: g_dfmt_p at third_party/gdtoa/g_dfmt_p.c:105
|
||||
// 413947: ConvertMatrixToStringTable at tool/viz/lib/formatmatrix-double.c:40
|
||||
// 413a5f: FormatMatrixDouble at tool/viz/lib/formatmatrix-double.c:55
|
||||
// 413b13: StringifyMatrixDouble at tool/viz/lib/formatmatrix-double.c:65
|
||||
// 464923: GetChromaticAdaptationMatrix_testD65ToD50_soWeCanCieLab at test/dsp/core/illumination_test.c:39
|
||||
// 4650c2: testlib_runtestcases at libc/testlib/testrunner.c:94
|
||||
// 464676: testlib_runalltests at libc/testlib/runner.c:37
|
||||
// 46455e: main at libc/testlib/testmain.c:84
|
||||
// 401d30: cosmo at libc/runtime/cosmo.S:65
|
||||
// 401173: _start at libc/crt/crt.S:67
|
||||
word0(&d) += (unsigned)(be + bbits - 1) << Exp_shift;
|
||||
#endif
|
||||
if (k >= 0 && k <= Ten_pmax) {
|
||||
if (dval(&d) < tens[k])
|
||||
|
|
|
@ -33,7 +33,7 @@ uint32_t EncodeRde(struct XedDecodedInst *x) {
|
|||
uint32_t osz = x->op.osz ^ x->op.realmode;
|
||||
return kWordLog2[~x->op.opcode & 1][osz][x->op.rexw] << 28 |
|
||||
x->op.mode << 26 | kXedEamode[x->op.asz][x->op.mode] << 24 |
|
||||
x->op.rep << 30 | x->op.mod << 22 | x->op.asz << 17 |
|
||||
(uint32_t)x->op.rep << 30 | x->op.mod << 22 | x->op.asz << 17 |
|
||||
x->op.seg_ovd << 18 | x->op.rexw << 6 | osz << 5 |
|
||||
(x->op.rex << 4 | x->op.rexb << 3 | x->op.srm) << 12 |
|
||||
(x->op.rex << 4 | x->op.rexb << 3 | x->op.rm) << 7 |
|
||||
|
|
|
@ -170,6 +170,7 @@
|
|||
"frownedupon"
|
||||
"wontreturn"
|
||||
"noasan"
|
||||
"noubsan"
|
||||
"initarray"
|
||||
"mayalias"
|
||||
"noinstrument"
|
||||
|
|
Loading…
Add table
Reference in a new issue