From b3838173ecbb67fae548008ae9a24ce7289fed1c Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 16 May 2021 11:16:28 -0700 Subject: [PATCH] Remove undefined behaviors --- libc/fmt/fmt.c | 15 +- libc/fmt/fmt.mk | 5 - libc/fmt/itoa128radix10.greg.c | 2 +- libc/fmt/itoa64.c | 2 +- libc/fmt/itoa64radix10.greg.c | 12 +- libc/integral/c.inc | 7 + libc/intrin/asan.c | 2 +- libc/intrin/intrin.mk | 10 +- libc/intrin/pabsd.c | 2 +- libc/intrin/paddd.c | 8 +- libc/intrin/paddd.h | 2 +- libc/intrin/paddq.c | 4 +- libc/intrin/paddq.h | 2 +- libc/intrin/phaddd.c | 2 +- libc/intrin/phaddd.h | 2 +- libc/intrin/phsubd.c | 4 +- libc/intrin/phsubd.h | 2 +- libc/intrin/pmulhuw.c | 6 +- libc/intrin/pmulld.c | 6 +- libc/intrin/pmulld.h | 2 +- libc/intrin/psignd.c | 2 +- libc/intrin/pslld.c | 2 +- libc/intrin/pslldq.c | 8 +- libc/intrin/psllwv.c | 9 +- libc/intrin/psrad.c | 9 +- libc/intrin/psradv.c | 9 +- libc/intrin/psraw.c | 9 +- libc/intrin/psrawv.c | 9 +- libc/intrin/psubd.c | 4 +- libc/intrin/psubd.h | 2 +- libc/intrin/psubq.c | 4 +- libc/intrin/psubq.h | 2 +- libc/intrin/ubsan.c | 593 +++++++++++++++++++++++++++++++ libc/log/die.c | 6 +- libc/log/showcrashreports.c | 2 - libc/log/somanyubsan.S | 528 --------------------------- libc/log/ubsan.c | 232 ------------ libc/log/ubsan.internal.h | 114 ------ libc/str/memccpy.c | 2 +- libc/str/memchr.c | 2 +- libc/str/memset-pure.c | 2 +- libc/str/rawmemchr.c | 2 +- libc/stubs/ubsan.S | 311 ---------------- test/libc/calls/sigaction_test.c | 6 +- test/libc/intrin/intrin_test.c | 56 ++- test/libc/intrin/pmulhrsw_test.c | 7 + third_party/gdtoa/g_xfmt.c | 4 +- third_party/gdtoa/g_xfmt_p.c | 4 +- third_party/gdtoa/gdtoa.c | 18 +- tool/build/lib/modrm.c | 2 +- tool/emacs/cosmo-c-keywords.el | 1 + 51 files changed, 756 insertions(+), 1302 deletions(-) create mode 100644 libc/intrin/ubsan.c delete mode 100644 libc/log/somanyubsan.S delete mode 100644 libc/log/ubsan.c delete mode 100644 libc/log/ubsan.internal.h delete mode 100644 libc/stubs/ubsan.S diff --git a/libc/fmt/fmt.c b/libc/fmt/fmt.c index 4f872a74f..add6f33c1 100644 --- a/libc/fmt/fmt.c +++ b/libc/fmt/fmt.c @@ -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; diff --git a/libc/fmt/fmt.mk b/libc/fmt/fmt.mk index e906da317..e73cc9299 100644 --- a/libc/fmt/fmt.mk +++ b/libc/fmt/fmt.mk @@ -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)) diff --git a/libc/fmt/itoa128radix10.greg.c b/libc/fmt/itoa128radix10.greg.c index 824c4af20..266d02114 100644 --- a/libc/fmt/itoa128radix10.greg.c +++ b/libc/fmt/itoa128radix10.greg.c @@ -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); } diff --git a/libc/fmt/itoa64.c b/libc/fmt/itoa64.c index 126e21838..c3c0e7017 100644 --- a/libc/fmt/itoa64.c +++ b/libc/fmt/itoa64.c @@ -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); } diff --git a/libc/fmt/itoa64radix10.greg.c b/libc/fmt/itoa64radix10.greg.c index 380411487..b49742f4a 100644 --- a/libc/fmt/itoa64radix10.greg.c +++ b/libc/fmt/itoa64radix10.greg.c @@ -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); } diff --git a/libc/integral/c.inc b/libc/integral/c.inc index 1eadabba6..9d009345c 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -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() diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index 7573af0c2..5e442eba8 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -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; diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk index d71f495e7..5faebf2f7 100644 --- a/libc/intrin/intrin.mk +++ b/libc/intrin/intrin.mk @@ -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 diff --git a/libc/intrin/pabsd.c b/libc/intrin/pabsd.c index d9ab15607..b01f3b12b 100644 --- a/libc/intrin/pabsd.c +++ b/libc/intrin/pabsd.c @@ -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); } diff --git a/libc/intrin/paddd.c b/libc/intrin/paddd.c index 019628279..e894c8adf 100644 --- a/libc/intrin/paddd.c +++ b/libc/intrin/paddd.c @@ -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); } diff --git a/libc/intrin/paddd.h b/libc/intrin/paddd.h index 110d5807c..29e936740 100644 --- a/libc/intrin/paddd.h +++ b/libc/intrin/paddd.h @@ -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) diff --git a/libc/intrin/paddq.c b/libc/intrin/paddq.c index 072166497..56168c91d 100644 --- a/libc/intrin/paddq.c +++ b/libc/intrin/paddq.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); } diff --git a/libc/intrin/paddq.h b/libc/intrin/paddq.h index 906f460b9..b7dc5635c 100644 --- a/libc/intrin/paddq.h +++ b/libc/intrin/paddq.h @@ -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) diff --git a/libc/intrin/phaddd.c b/libc/intrin/phaddd.c index 465c01d87..8ead1b4bb 100644 --- a/libc/intrin/phaddd.c +++ b/libc/intrin/phaddd.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]; diff --git a/libc/intrin/phaddd.h b/libc/intrin/phaddd.h index 96e68bd8a..7751dd1c6 100644 --- a/libc/intrin/phaddd.h +++ b/libc/intrin/phaddd.h @@ -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) diff --git a/libc/intrin/phsubd.c b/libc/intrin/phsubd.c index 5285c3772..c8efc0430 100644 --- a/libc/intrin/phsubd.c +++ b/libc/intrin/phsubd.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]; diff --git a/libc/intrin/phsubd.h b/libc/intrin/phsubd.h index 641272fb9..a35a2b266 100644 --- a/libc/intrin/phsubd.h +++ b/libc/intrin/phsubd.h @@ -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) diff --git a/libc/intrin/pmulhuw.c b/libc/intrin/pmulhuw.c index 2c162fa3b..0614cdedd 100644 --- a/libc/intrin/pmulhuw.c +++ b/libc/intrin/pmulhuw.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); } diff --git a/libc/intrin/pmulld.c b/libc/intrin/pmulld.c index 9b7fe9e5f..b8c29dee9 100644 --- a/libc/intrin/pmulld.c +++ b/libc/intrin/pmulld.c @@ -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]; } diff --git a/libc/intrin/pmulld.h b/libc/intrin/pmulld.h index 8365f5b1c..74e9563ae 100644 --- a/libc/intrin/pmulld.h +++ b/libc/intrin/pmulld.h @@ -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) diff --git a/libc/intrin/psignd.c b/libc/intrin/psignd.c index 0ff4fc19e..2ae6e6c35 100644 --- a/libc/intrin/psignd.c +++ b/libc/intrin/psignd.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]; } diff --git a/libc/intrin/pslld.c b/libc/intrin/pslld.c index a8c570ab6..18f342dc2 100644 --- a/libc/intrin/pslld.c +++ b/libc/intrin/pslld.c @@ -26,8 +26,8 @@ * @mayalias */ void(pslld)(uint32_t a[4], const uint32_t b[4], unsigned char c) { + unsigned i; if (c <= 31) { - unsigned i; for (i = 0; i < 4; ++i) { a[i] = b[i] << c; } diff --git a/libc/intrin/pslldq.c b/libc/intrin/pslldq.c index 8d6e5129e..74115e46d 100644 --- a/libc/intrin/pslldq.c +++ b/libc/intrin/pslldq.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); } diff --git a/libc/intrin/psllwv.c b/libc/intrin/psllwv.c index abb7f7b88..08da0d7ad 100644 --- a/libc/intrin/psllwv.c +++ b/libc/intrin/psllwv.c @@ -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); } } diff --git a/libc/intrin/psrad.c b/libc/intrin/psrad.c index c6fda7ed6..694998048 100644 --- a/libc/intrin/psrad.c +++ b/libc/intrin/psrad.c @@ -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; } } diff --git a/libc/intrin/psradv.c b/libc/intrin/psradv.c index 36e49eb94..8506a4ffa 100644 --- a/libc/intrin/psradv.c +++ b/libc/intrin/psradv.c @@ -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; } } diff --git a/libc/intrin/psraw.c b/libc/intrin/psraw.c index 0ab46b0da..d263cf094 100644 --- a/libc/intrin/psraw.c +++ b/libc/intrin/psraw.c @@ -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; } } diff --git a/libc/intrin/psrawv.c b/libc/intrin/psrawv.c index b1109bf83..0024bffb4 100644 --- a/libc/intrin/psrawv.c +++ b/libc/intrin/psrawv.c @@ -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; } } diff --git a/libc/intrin/psubd.c b/libc/intrin/psubd.c index 0df04acfe..f93d9dac5 100644 --- a/libc/intrin/psubd.c +++ b/libc/intrin/psubd.c @@ -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]; } diff --git a/libc/intrin/psubd.h b/libc/intrin/psubd.h index c8f396da4..4aa30b9ce 100644 --- a/libc/intrin/psubd.h +++ b/libc/intrin/psubd.h @@ -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) diff --git a/libc/intrin/psubq.c b/libc/intrin/psubq.c index 363afc35c..495f6d5ca 100644 --- a/libc/intrin/psubq.c +++ b/libc/intrin/psubq.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]; } diff --git a/libc/intrin/psubq.h b/libc/intrin/psubq.h index d08bb6f7c..9b4a5d3b9 100644 --- a/libc/intrin/psubq.h +++ b/libc/intrin/psubq.h @@ -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) diff --git a/libc/intrin/ubsan.c b/libc/intrin/ubsan.c new file mode 100644 index 000000000..150133fca --- /dev/null +++ b/libc/intrin/ubsan.c @@ -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 = { + "", + 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; +} diff --git a/libc/log/die.c b/libc/log/die.c index 066c27682..998598564 100644 --- a/libc/log/die.c +++ b/libc/log/die.c @@ -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); - } + if (IsDebuggerPresent(false)) DebugBreak(); + ShowBacktrace(2, NULL); } exit(77); } diff --git a/libc/log/showcrashreports.c b/libc/log/showcrashreports.c index d7a0b726d..c07acccf7 100644 --- a/libc/log/showcrashreports.c +++ b/libc/log/showcrashreports.c @@ -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]; diff --git a/libc/log/somanyubsan.S b/libc/log/somanyubsan.S deleted file mode 100644 index 98dbb7601..000000000 --- a/libc/log/somanyubsan.S +++ /dev/null @@ -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 diff --git a/libc/log/ubsan.c b/libc/log/ubsan.c deleted file mode 100644 index ee64cd9ef..000000000 --- a/libc/log/ubsan.c +++ /dev/null @@ -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 = { - "", - pushpop(0), - pushpop(0), - }; - __ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow"); -#endif -} diff --git a/libc/log/ubsan.internal.h b/libc/log/ubsan.internal.h deleted file mode 100644 index f9dc4fd4e..000000000 --- a/libc/log/ubsan.internal.h +++ /dev/null @@ -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_ */ diff --git a/libc/str/memccpy.c b/libc/str/memccpy.c index 708a85fe5..f809cd0ff 100644 --- a/libc/str/memccpy.c +++ b/libc/str/memccpy.c @@ -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; diff --git a/libc/str/memchr.c b/libc/str/memchr.c index c764a9d08..c44f48380 100644 --- a/libc/str/memchr.c +++ b/libc/str/memchr.c @@ -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 | diff --git a/libc/str/memset-pure.c b/libc/str/memset-pure.c index 951629f7e..cf1fe8e7d 100644 --- a/libc/str/memset-pure.c +++ b/libc/str/memset-pure.c @@ -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; diff --git a/libc/str/rawmemchr.c b/libc/str/rawmemchr.c index 4ffd31621..8538fd611 100644 --- a/libc/str/rawmemchr.c +++ b/libc/str/rawmemchr.c @@ -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; } diff --git a/libc/stubs/ubsan.S b/libc/stubs/ubsan.S deleted file mode 100644 index d441e81d6..000000000 --- a/libc/stubs/ubsan.S +++ /dev/null @@ -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 diff --git a/test/libc/calls/sigaction_test.c b/test/libc/calls/sigaction_test.c index e96615d16..1d9d7c8e2 100644 --- a/test/libc/calls/sigaction_test.c +++ b/test/libc/calls/sigaction_test.c @@ -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(); +} diff --git a/test/libc/intrin/intrin_test.c b/test/libc/intrin/intrin_test.c index 8b50bd8d0..b9b4a3b59 100644 --- a/test/libc/intrin/intrin_test.c +++ b/test/libc/intrin/intrin_test.c @@ -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)); diff --git a/test/libc/intrin/pmulhrsw_test.c b/test/libc/intrin/pmulhrsw_test.c index 2ddda913e..aa6d06309 100644 --- a/test/libc/intrin/pmulhrsw_test.c +++ b/test/libc/intrin/pmulhrsw_test.c @@ -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) { diff --git a/third_party/gdtoa/g_xfmt.c b/third_party/gdtoa/g_xfmt.c index b6b1b1e28..b2439ab95 100644 --- a/third_party/gdtoa/g_xfmt.c +++ b/third_party/gdtoa/g_xfmt.c @@ -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 */ diff --git a/third_party/gdtoa/g_xfmt_p.c b/third_party/gdtoa/g_xfmt_p.c index 29ee7ecb6..fb8856290 100644 --- a/third_party/gdtoa/g_xfmt_p.c +++ b/third_party/gdtoa/g_xfmt_p.c @@ -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 */ diff --git a/third_party/gdtoa/gdtoa.c b/third_party/gdtoa/gdtoa.c index 70d2573ed..bb46f89f3 100644 --- a/third_party/gdtoa/gdtoa.c +++ b/third_party/gdtoa/gdtoa.c @@ -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]) diff --git a/tool/build/lib/modrm.c b/tool/build/lib/modrm.c index 99d2b3f65..b2d46fdf1 100644 --- a/tool/build/lib/modrm.c +++ b/tool/build/lib/modrm.c @@ -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 | diff --git a/tool/emacs/cosmo-c-keywords.el b/tool/emacs/cosmo-c-keywords.el index bd3372244..a5970c1ea 100644 --- a/tool/emacs/cosmo-c-keywords.el +++ b/tool/emacs/cosmo-c-keywords.el @@ -170,6 +170,7 @@ "frownedupon" "wontreturn" "noasan" + "noubsan" "initarray" "mayalias" "noinstrument"