Restart CI for New Technology and UBSAN hunting

Continuous Integration (via runit and runitd) is now re-enabled on win7
and win10. The `make test` command, which runs the tests on all systems
is now the fastest and most stable it's been since the project started.

UBSAN is now enabled in MODE=dbg in addition to ASAN. Many instances of
undefined behavior have been removed. Mostly things like passing a NULL
argument to memcpy(), which works fine with Cosmopolitan Libc, but that
doesn't prevents the compiler from being unhappy. There was an issue w/
GNU make where static analysis claims a sprintf() call can overflow. We
also now have nicer looking crash reports on Windows since uname should
now be supported and msys64 addr2line works reliably.
This commit is contained in:
Justine Tunney 2022-03-21 03:46:16 -07:00
parent d5ff2c3fb9
commit 5e8ae2d5bc
80 changed files with 506 additions and 249 deletions

View file

@ -22,11 +22,11 @@
#include "libc/nt/systeminfo.h"
#include "libc/str/str.h"
textwindows int gethostname_nt(char *name, size_t len) {
textwindows int gethostname_nt(char *name, size_t len, int kind) {
uint32_t nSize;
char16_t name16[256];
nSize = ARRAYLEN(name16);
if (GetComputerNameEx(kNtComputerNamePhysicalDnsHostname, name16, &nSize)) {
if (GetComputerNameEx(kind, name16, &nSize)) {
tprecode16to8(name, len, name16);
return 0;
} else {

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nt/enum/computernameformat.h"
#include "libc/sysv/errfuns.h"
/**
@ -37,6 +38,6 @@ int gethostname(char *name, size_t len) {
return gethostname_bsd(name, len);
}
} else {
return gethostname_nt(name, len);
return gethostname_nt(name, len, kNtComputerNamePhysicalDnsHostname);
}
}

View file

@ -234,7 +234,7 @@ void __sigenter_xnu(void *, i32, i32, struct __darwin_siginfo *,
struct __darwin_ucontext *) hidden;
int gethostname_linux(char *, size_t) hidden;
int gethostname_bsd(char *, size_t) hidden;
int gethostname_nt(char *, size_t) hidden;
int gethostname_nt(char *, size_t, int) hidden;
size_t __iovec_size(const struct iovec *, size_t) hidden;
void __rusage2linux(struct rusage *) hidden;
int __notziposat(int, const char *);

View file

@ -24,6 +24,7 @@
textwindows void ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
if (!cr) return;
ctx->uc_flags = cr->EFlags;
ctx->uc_mcontext.gregs[REG_EFL] = cr->EFlags;
ctx->uc_mcontext.rax = cr->Rax;
ctx->uc_mcontext.rbx = cr->Rbx;
ctx->uc_mcontext.rcx = cr->Rcx;

View file

@ -18,34 +18,72 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/utsname.h"
#include "libc/dce.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nt/enum/computernameformat.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
static inline textwindows noasan int NtGetMajorVersion(void) {
return NtGetPeb()->OSMajorVersion;
}
static inline textwindows noasan int NtGetMinorVersion(void) {
return NtGetPeb()->OSMinorVersion;
}
static inline textwindows noasan int NtGetBuildNumber(void) {
return NtGetPeb()->OSBuildNumber;
}
/**
* Asks kernel to give us the `uname -a` data.
* @return 0 on success, or -1 w/ errno
*/
int uname(struct utsname *lool) {
char *out;
int rc, v;
char *out, *p;
size_t i, j, len;
char tmp[sizeof(struct utsname)];
bzero(tmp, sizeof(tmp));
if (sys_uname(tmp) != -1) {
out = (char *)lool;
i = 0;
j = 0;
for (;;) {
len = strlen(&tmp[j]);
if (len >= sizeof(struct utsname) - i) break;
memcpy(&out[i], &tmp[j], len + 1);
i += SYS_NMLN;
j += len;
while (j < sizeof(tmp) && tmp[j] == '\0') ++j;
if (j == sizeof(tmp)) break;
}
return 0;
if (!lool) return efault();
if (!lool || (IsAsan() && !__asan_is_valid(lool, sizeof(*lool)))) {
rc = efault();
} else {
bzero(lool, sizeof(struct utsname));
return -1;
bzero(tmp, sizeof(tmp));
if (!IsWindows()) {
if ((rc = sys_uname(tmp)) != -1) {
out = (char *)lool;
for (i = j = 0;;) {
len = strlen(&tmp[j]);
if (len >= sizeof(struct utsname) - i) break;
memcpy(&out[i], &tmp[j], len + 1);
i += SYS_NMLN;
j += len;
while (j < sizeof(tmp) && tmp[j] == '\0') ++j;
if (j == sizeof(tmp)) break;
}
}
} else {
v = NtGetVersion();
p = lool->version;
p = FormatUint32(p, NtGetMajorVersion()), *p++ = '.';
p = FormatUint32(p, NtGetMinorVersion()), *p++ = '-';
p = FormatUint32(p, NtGetBuildNumber());
strcpy(lool->sysname, "The New Technology");
strcpy(lool->machine, "x86_64");
rc = gethostname_nt(lool->nodename, sizeof(lool->nodename),
kNtComputerNamePhysicalDnsHostname);
rc |= gethostname_nt(lool->domainname, sizeof(lool->domainname),
kNtComputerNamePhysicalDnsDomain);
}
}
STRACE("uname([%s, %s, %s, %s, %s, %s]) → %d% m", lool->sysname,
lool->nodename, lool->release, lool->version, lool->machine,
lool->domainname, rc);
return rc;
}

View file

@ -24,9 +24,10 @@
#include "libc/nt/enum/signal.h"
#include "libc/nt/struct/ntexceptionpointers.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sicode.h"
textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
int sig, rva;
int sig, rva, code;
struct Goodies {
ucontext_t ctx;
struct siginfo si;
@ -34,44 +35,69 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
STRACE("__wincrash");
switch (ep->ExceptionRecord->ExceptionCode) {
case kNtSignalBreakpoint:
code = TRAP_BRKPT;
sig = SIGTRAP;
break;
case kNtSignalIllegalInstruction:
code = ILL_ILLOPC;
sig = SIGILL;
break;
case kNtSignalPrivInstruction:
code = ILL_PRVOPC;
sig = SIGILL;
break;
case kNtSignalGuardPage:
case kNtSignalAccessViolation:
case kNtSignalInPageError:
code = SEGV_MAPERR;
sig = SIGSEGV;
break;
case kNtSignalAccessViolation:
code = SEGV_ACCERR;
sig = SIGSEGV;
break;
case kNtSignalInvalidHandle:
case kNtSignalInvalidParameter:
case kNtSignalAssertionFailure:
code = SI_USER;
sig = SIGABRT;
break;
case kNtSignalFltDenormalOperand:
case kNtSignalFltDivideByZero:
case kNtSignalFltInexactResult:
case kNtSignalFltInvalidOperation:
code = FPE_FLTDIV;
sig = SIGFPE;
break;
case kNtSignalFltOverflow:
case kNtSignalFltStackCheck:
code = FPE_FLTOVF;
sig = SIGFPE;
break;
case kNtSignalFltUnderflow:
code = FPE_FLTUND;
sig = SIGFPE;
break;
case kNtSignalFltInexactResult:
code = FPE_FLTRES;
sig = SIGFPE;
break;
case kNtSignalFltDenormalOperand:
case kNtSignalFltInvalidOperation:
case kNtSignalFltStackCheck:
case kNtSignalIntegerDivideByZero:
case kNtSignalFloatMultipleFaults:
case kNtSignalFloatMultipleTraps:
code = FPE_FLTINV;
sig = SIGFPE;
break;
case kNtSignalDllNotFound:
case kNtSignalOrdinalNotFound:
case kNtSignalEntrypointNotFound:
case kNtSignalDllInitFailed:
code = SI_KERNEL;
sig = SIGSYS;
break;
default:
return kNtExceptionContinueSearch;
}
bzero(&g, sizeof(g));
g.si.si_code = code;
rva = __sighandrvas[sig];
if (rva >= kSigactionMinRva) {
ntcontext2linux(&g.ctx, ep->ContextRecord);

View file

@ -57,7 +57,7 @@
#define IsOptimized() 0
#endif
#ifdef __FSANITIZE_ADDRESS__
#ifdef __SANITIZE_ADDRESS__
#define IsAsan() 1
#else
#define IsAsan() 0

View file

@ -43,9 +43,6 @@
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/prot.h"
#define MAXT (24 * 60 * 60 * 1000000000ull)
#define WRAP ((MAXT + 1) / 10 * 33)
struct Timestamps {
unsigned long long birth;
unsigned long long start;
@ -56,6 +53,13 @@ extern bool __replmode;
extern bool __nomultics;
volatile unsigned long long __kbirth;
static inline uint64_t ClocksToNanos(uint64_t x, uint64_t y) {
// approximation of round(x*.323018) which is usually
// the ratio between inva rdtsc ticks and nanoseconds
uint128_t difference = x - y;
return (difference * 338709) >> 20;
}
privileged static struct Timestamps kenter(void) {
struct Timestamps ts;
ts.start = rdtsc();
@ -336,7 +340,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
}
continue;
case 'T':
x = unsignedsubtract(ts.start, ts.birth) % WRAP * 10 / 33;
x = ClocksToNanos(ts.start, ts.birth) % 86400000000000;
goto FormatUnsigned;
case 'P':
if (!__vforked) {

View file

@ -22,6 +22,7 @@
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/color.internal.h"
#include "libc/log/internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
@ -37,6 +38,8 @@
#define kUbsanKindFloat 1
#define kUbsanKindUnknown 0xffff
typedef void __ubsan_die_f(void);
struct UbsanSourceLocation {
const char *file;
uint32_t line;
@ -188,17 +191,42 @@ static uintptr_t __ubsan_extend(struct UbsanTypeDescriptor *t, uintptr_t x) {
return x;
}
void __ubsan_abort(const struct UbsanSourceLocation *loc,
const char *description) {
kprintf("%n%s:%d: ubsan error: %s%n", loc->file, loc->line, description);
if (weaken(__die)) weaken(__die)();
_Exit(134);
static wontreturn void __ubsan_unreachable(void) {
for (;;) __builtin_trap();
}
static void __ubsan_exit(void) {
kprintf("your ubsan runtime needs%n"
"\tSTATIC_YOINK(\"__die\");%n"
"in order to show you backtraces%n");
_Exit(99);
}
nodiscard static __ubsan_die_f *__ubsan_die(void) {
if (weaken(__die)) {
return weaken(__die);
} else {
return __ubsan_exit;
}
}
static void __ubsan_warning(const struct UbsanSourceLocation *loc,
const char *description) {
kprintf("%s:%d: %subsan warning: %s is undefined behavior%s%n", loc->file,
loc->line, SUBTLE, description, RESET);
}
nodiscard __ubsan_die_f *__ubsan_abort(const struct UbsanSourceLocation *loc,
const char *description) {
kprintf("%n%s:%d: %subsan error%s: %s%n", loc->file, loc->line, RED2, RESET,
description);
return __ubsan_die();
}
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";
return "negative shift exponent";
} else if (rhs >= __ubsan_bits(info->lhs_type)) {
return "shift exponent too large for type";
} else if (__ubsan_negative(info->lhs_type, lhs)) {
@ -210,9 +238,10 @@ static const char *__ubsan_describe_shift(
}
}
void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
uintptr_t lhs, uintptr_t rhs) {
char buf[512], *p = buf;
static char *__ubsan_describe_shift_out_of_bounds(
char buf[512], struct UbsanShiftOutOfBoundsInfo *info, uintptr_t lhs,
uintptr_t rhs) {
char *p = buf;
lhs = __ubsan_extend(info->lhs_type, lhs);
rhs = __ubsan_extend(info->rhs_type, rhs);
p = __stpcpy(p, __ubsan_describe_shift(info, lhs, rhs)), *p++ = ' ';
@ -220,12 +249,22 @@ void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
p = __stpcpy(p, info->lhs_type->name), *p++ = ' ';
p = __ubsan_itpcpy(p, info->rhs_type, rhs), *p++ = ' ';
p = __stpcpy(p, info->rhs_type->name);
__ubsan_abort(&info->location, buf);
return buf;
}
void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
uintptr_t lhs, uintptr_t rhs) {
char buf[512];
__ubsan_warning(&info->location,
__ubsan_describe_shift_out_of_bounds(buf, info, lhs, rhs));
}
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);
char buf[512];
__ubsan_abort(&info->location,
__ubsan_describe_shift_out_of_bounds(buf, info, lhs, rhs))();
__ubsan_unreachable();
}
void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
@ -237,7 +276,8 @@ void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
p = __stpcpy(p, " into ");
p = __stpcpy(p, info->array_type->name);
p = __stpcpy(p, " out of bounds");
__ubsan_abort(&info->location, buf);
__ubsan_abort(&info->location, buf)();
__ubsan_unreachable();
}
void __ubsan_handle_out_of_bounds_abort(struct UbsanOutOfBoundsInfo *info,
@ -245,11 +285,11 @@ void __ubsan_handle_out_of_bounds_abort(struct UbsanOutOfBoundsInfo *info,
__ubsan_handle_out_of_bounds(info, index);
}
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
uintptr_t pointer) {
static __ubsan_die_f *__ubsan_type_mismatch_handler(
struct UbsanTypeMismatchInfo *info, uintptr_t pointer) {
const char *kind;
char buf[512], *p = buf;
if (!pointer) __ubsan_abort(&info->location, "null pointer access");
if (!pointer) return __ubsan_abort(&info->location, "null pointer access");
kind = __ubsan_dubnul(kUbsanTypeCheckKinds, info->type_check_kind);
if (info->alignment && (pointer & (info->alignment - 1))) {
p = __stpcpy(p, "unaligned ");
@ -266,41 +306,57 @@ void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
p = __stpcpy(p, " with insufficient space for object of type ");
p = __stpcpy(p, info->type->name);
}
__ubsan_abort(&info->location, buf);
return __ubsan_abort(&info->location, buf);
}
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
uintptr_t pointer) {
__ubsan_type_mismatch_handler(info, pointer)();
__ubsan_unreachable();
}
void __ubsan_handle_type_mismatch_abort(struct UbsanTypeMismatchInfo *info,
uintptr_t pointer) {
__ubsan_handle_type_mismatch(info, pointer);
__ubsan_type_mismatch_handler(info, pointer)();
__ubsan_unreachable();
}
void __ubsan_handle_type_mismatch_v1(
static __ubsan_die_f *__ubsan_type_mismatch_v1_handler(
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);
return __ubsan_type_mismatch_handler(&mm, pointer);
}
void __ubsan_handle_type_mismatch_v1(
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
__ubsan_type_mismatch_v1_handler(type_mismatch, pointer)();
__ubsan_unreachable();
}
void __ubsan_handle_type_mismatch_v1_abort(
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
__ubsan_handle_type_mismatch_v1(type_mismatch, pointer);
__ubsan_type_mismatch_v1_handler(type_mismatch, pointer)();
__ubsan_unreachable();
}
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");
__ubsan_abort(&data->location, "float cast overflow")();
__ubsan_unreachable();
#else
const struct UbsanSourceLocation kUnknownLocation = {
"<unknown file>",
pushpop(0),
pushpop(0),
};
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow");
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow")();
__ubsan_unreachable();
#endif
}
@ -309,7 +365,8 @@ void __ubsan_handle_float_cast_overflow_abort(void *data_raw, void *from_raw) {
}
void __ubsan_handle_add_overflow(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "add overflow");
__ubsan_abort(loc, "add overflow")();
__ubsan_unreachable();
}
void __ubsan_handle_add_overflow_abort(const struct UbsanSourceLocation *loc) {
@ -318,7 +375,8 @@ void __ubsan_handle_add_overflow_abort(const struct UbsanSourceLocation *loc) {
void __ubsan_handle_alignment_assumption(
const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "alignment assumption");
__ubsan_abort(loc, "alignment assumption")();
__ubsan_unreachable();
}
void __ubsan_handle_alignment_assumption_abort(
@ -327,7 +385,8 @@ void __ubsan_handle_alignment_assumption_abort(
}
void __ubsan_handle_builtin_unreachable(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "builtin unreachable");
__ubsan_abort(loc, "builtin unreachable")();
__ubsan_unreachable();
}
void __ubsan_handle_builtin_unreachable_abort(
@ -336,7 +395,8 @@ void __ubsan_handle_builtin_unreachable_abort(
}
void __ubsan_handle_cfi_bad_type(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "cfi bad type");
__ubsan_abort(loc, "cfi bad type")();
__ubsan_unreachable();
}
void __ubsan_handle_cfi_bad_type_abort(const struct UbsanSourceLocation *loc) {
@ -344,7 +404,8 @@ void __ubsan_handle_cfi_bad_type_abort(const struct UbsanSourceLocation *loc) {
}
void __ubsan_handle_cfi_check_fail(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "cfi check fail");
__ubsan_abort(loc, "cfi check fail")();
__ubsan_unreachable();
}
void __ubsan_handle_cfi_check_fail_abort(
@ -353,7 +414,8 @@ void __ubsan_handle_cfi_check_fail_abort(
}
void __ubsan_handle_divrem_overflow(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "divrem overflow");
__ubsan_abort(loc, "divrem overflow")();
__ubsan_unreachable();
}
void __ubsan_handle_divrem_overflow_abort(
@ -363,7 +425,8 @@ void __ubsan_handle_divrem_overflow_abort(
void __ubsan_handle_dynamic_type_cache_miss(
const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "dynamic type cache miss");
__ubsan_abort(loc, "dynamic type cache miss")();
__ubsan_unreachable();
}
void __ubsan_handle_dynamic_type_cache_miss_abort(
@ -373,7 +436,8 @@ void __ubsan_handle_dynamic_type_cache_miss_abort(
void __ubsan_handle_function_type_mismatch(
const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "function type mismatch");
__ubsan_abort(loc, "function type mismatch")();
__ubsan_unreachable();
}
void __ubsan_handle_function_type_mismatch_abort(
@ -382,7 +446,8 @@ void __ubsan_handle_function_type_mismatch_abort(
}
void __ubsan_handle_implicit_conversion(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "implicit conversion");
__ubsan_abort(loc, "implicit conversion")();
__ubsan_unreachable();
}
void __ubsan_handle_implicit_conversion_abort(
@ -391,7 +456,8 @@ void __ubsan_handle_implicit_conversion_abort(
}
void __ubsan_handle_invalid_builtin(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "invalid builtin");
__ubsan_abort(loc, "invalid builtin")();
__ubsan_unreachable();
}
void __ubsan_handle_invalid_builtin_abort(
@ -400,7 +466,8 @@ void __ubsan_handle_invalid_builtin_abort(
}
void __ubsan_handle_load_invalid_value(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "load invalid value (uninitialized? bool∌[01]?)");
__ubsan_abort(loc, "load invalid value (uninitialized? bool∌[01]?)")();
__ubsan_unreachable();
}
void __ubsan_handle_load_invalid_value_abort(
@ -409,7 +476,8 @@ void __ubsan_handle_load_invalid_value_abort(
}
void __ubsan_handle_missing_return(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "missing return");
__ubsan_abort(loc, "missing return")();
__ubsan_unreachable();
}
void __ubsan_handle_missing_return_abort(
@ -418,7 +486,8 @@ void __ubsan_handle_missing_return_abort(
}
void __ubsan_handle_mul_overflow(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "multiply overflow");
__ubsan_abort(loc, "multiply overflow")();
__ubsan_unreachable();
}
void __ubsan_handle_mul_overflow_abort(const struct UbsanSourceLocation *loc) {
@ -426,7 +495,8 @@ void __ubsan_handle_mul_overflow_abort(const struct UbsanSourceLocation *loc) {
}
void __ubsan_handle_negate_overflow(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "negate overflow");
__ubsan_abort(loc, "negate overflow")();
__ubsan_unreachable();
}
void __ubsan_handle_negate_overflow_abort(
@ -435,24 +505,28 @@ void __ubsan_handle_negate_overflow_abort(
}
void __ubsan_handle_nonnull_arg(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "nonnull argument");
__ubsan_warning(loc, "null argument here");
}
void __ubsan_handle_nonnull_arg_abort(const struct UbsanSourceLocation *loc) {
__ubsan_handle_nonnull_arg(loc);
__ubsan_abort(loc, "nonnull argument")();
__ubsan_unreachable();
}
void __ubsan_handle_nonnull_return_v1(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "non-null return (v1)");
__ubsan_abort(loc, "non-null return (v1)")();
__ubsan_unreachable();
}
void __ubsan_handle_nonnull_return_v1_abort(
const struct UbsanSourceLocation *loc) {
__ubsan_handle_nonnull_return_v1(loc);
__ubsan_abort(loc, "non-null return (v1)")();
__ubsan_unreachable();
}
void __ubsan_handle_nullability_arg(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "nullability arg");
__ubsan_abort(loc, "nullability arg")();
__ubsan_unreachable();
}
void __ubsan_handle_nullability_arg_abort(
@ -462,7 +536,8 @@ void __ubsan_handle_nullability_arg_abort(
void __ubsan_handle_nullability_return_v1(
const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "nullability return (v1)");
__ubsan_abort(loc, "nullability return (v1)")();
__ubsan_unreachable();
}
void __ubsan_handle_nullability_return_v1_abort(
@ -471,7 +546,8 @@ void __ubsan_handle_nullability_return_v1_abort(
}
void __ubsan_handle_pointer_overflow(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "pointer overflow");
__ubsan_abort(loc, "pointer overflow")();
__ubsan_unreachable();
}
void __ubsan_handle_pointer_overflow_abort(
@ -480,7 +556,8 @@ void __ubsan_handle_pointer_overflow_abort(
}
void __ubsan_handle_sub_overflow(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "subtract overflow");
__ubsan_abort(loc, "subtract overflow")();
__ubsan_unreachable();
}
void __ubsan_handle_sub_overflow_abort(const struct UbsanSourceLocation *loc) {
@ -489,7 +566,8 @@ void __ubsan_handle_sub_overflow_abort(const struct UbsanSourceLocation *loc) {
void __ubsan_handle_vla_bound_not_positive(
const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "vla bound not positive");
__ubsan_abort(loc, "vla bound not positive")();
__ubsan_unreachable();
}
void __ubsan_handle_vla_bound_not_positive_abort(
@ -498,7 +576,8 @@ void __ubsan_handle_vla_bound_not_positive_abort(
}
void __ubsan_handle_nonnull_return(const struct UbsanSourceLocation *loc) {
__ubsan_abort(loc, "nonnull return");
__ubsan_abort(loc, "nonnull return")();
__ubsan_unreachable();
}
void __ubsan_handle_nonnull_return_abort(

View file

@ -42,7 +42,7 @@
* possible UX for debugging your app, for varying levels of available
* information, on most of the various platforms.
*
* Before calling this function, consider placing showcrashreports() in
* Before calling this function, consider placing ShowCrashReports() in
* your main function and calling DebugBreak() wherever you want; it's
* safer. Also note the "GDB" environment variable can be set to empty
* string, as a fail-safe for disabling this behavior.

View file

@ -79,7 +79,7 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
* DWARF is a weak standard. Platforms that use LLVM or old GNU
* usually can't be counted upon to print backtraces correctly.
*/
if (!IsLinux() /* && !IsWindows() */) {
if (!IsLinux() && !IsWindows()) {
ShowHint("won't print addr2line backtrace because probably llvm");
return -1;
}

View file

@ -231,7 +231,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
? "Stack Overflow"
: GetSiCodeName(sig, si->si_code),
host, __getpid(), program_invocation_name, names.sysname,
names.nodename, names.release, names.version);
names.version, names.nodename, names.release);
if (ctx) {
kprintf("%n");
ShowFunctionCalls(ctx);

View file

@ -51,7 +51,7 @@ textexit static void __onkill(int sig, struct siginfo *si,
/**
* Installs default handlers for friendly kill signals.
* @see showcrashreports()
* @see ShowCrashReports()
*/
void callexitontermination(sigset_t *opt_out_exitsigs) {
struct sigaction sa;

View file

@ -195,7 +195,7 @@
.endm
.macro .poison name:req kind:req
#ifdef __FSANITIZE_ADDRESS__
#ifdef __SANITIZE_ADDRESS__
2323: .quad 0
.init.start 304,"_init_\name\()_poison_\@"
push %rdi
@ -211,13 +211,13 @@
.endm
.macro .underrun
#ifdef __FSANITIZE_ADDRESS__
#ifdef __SANITIZE_ADDRESS__
.poison __BASE_FILE__, kAsanGlobalUnderrun
#endif
.endm
.macro .overrun
#ifdef __FSANITIZE_ADDRESS__
#ifdef __SANITIZE_ADDRESS__
.poison __BASE_FILE__, kAsanGlobalUnderrun
#endif
.endm

View file

@ -16,45 +16,30 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nt/dll.h"
#include "libc/nt/enum/exceptionhandleractions.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/memflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/enum/wt.h"
#include "libc/nt/files.h"
#include "libc/nt/ipc.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/signals.h"
#include "libc/nt/struct/context.h"
#include "libc/nt/struct/ntexceptionpointers.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thread.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
extern int __pid;
extern unsigned long long __kbirth;

View file

@ -102,15 +102,15 @@ textstartup void __printargs(int argc, char **argv, char **envp,
}
}
STRACE("SPECIALS");
STRACE(" ☼ %21s = %#s", "kTmpPath", kTmpPath);
STRACE(" ☼ %21s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
STRACE(" ☼ %21s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory);
STRACE(" ☼ %21s = %#s", "program_executable_name", program_executable_name);
STRACE(" ☼ %21s = %#s", "GetInterpreterExecutableName()",
STRACE(" ☼ %30s = %#s", "kTmpPath", kTmpPath);
STRACE(" ☼ %30s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
STRACE(" ☼ %30s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory);
STRACE(" ☼ %30s = %#s", "program_executable_name", program_executable_name);
STRACE(" ☼ %30s = %#s", "GetInterpreterExecutableName()",
GetInterpreterExecutableName(path, sizeof(path)));
STRACE(" ☼ %21s = %p", "RSP", __builtin_frame_address(0));
STRACE(" ☼ %21s = %p", "GetStackAddr()", GetStackAddr(0));
STRACE(" ☼ %21s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
STRACE(" ☼ %21s = %p", "GetStackSize()", GetStackSize());
STRACE(" ☼ %30s = %p", "RSP", __builtin_frame_address(0));
STRACE(" ☼ %30s = %p", "GetStackAddr()", GetStackAddr(0));
STRACE(" ☼ %30s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
STRACE(" ☼ %30s = %p", "GetStackSize()", GetStackSize());
#endif
}

View file

@ -36,7 +36,7 @@
// @returnstwice
// @vforksafe
vfork:
#ifdef __FSANITIZE_ADDRESS__
#ifdef __SANITIZE_ADDRESS__
jmp fork # TODO: asan and vfork don't mix?
.endfn vfork,globl
#else
@ -98,4 +98,4 @@ vfork.bsd:
.previous
#endif /* DEBUGSYS */
#endif /* __FSANITIZE_ADDRESS__ */
#endif /* __SANITIZE_ADDRESS__ */

View file

@ -59,7 +59,11 @@ ssize_t appendd(char **b, const void *s, size_t l) {
return -1;
}
}
*(char *)mempcpy(p + z.i, s, l) = 0;
if (l) {
*(char *)mempcpy(p + z.i, s, l) = 0;
} else {
p[z.i] = 0;
}
z.i += l;
if (!IsTiny() && W == 8) z.i |= (size_t)APPEND_COOKIE << 48;
*(size_t *)(p + z.n - W) = z.i;

View file

@ -53,7 +53,7 @@ size_t fread(void *buf, size_t stride, size_t count, FILE *f) {
p = buf;
n = stride * count;
m = f->end - f->beg;
memcpy(p, f->buf + f->beg, MIN(n, m));
if (MIN(n, m)) memcpy(p, f->buf + f->beg, MIN(n, m));
if (n < m) {
f->beg += n;
return count;

View file

@ -35,6 +35,9 @@ uint32_t crc32c(uint32_t init, const void *data, size_t size) {
pe = p + size;
h = init ^ 0xffffffff;
if (X86_HAVE(SSE4_2)) {
while (p < pe && ((intptr_t)p & 7)) {
h = h >> 8 ^ kCrc32cTab[(h & 0xff) ^ *p++];
}
for (; p + 8 <= pe; p += 8) {
asm("crc32q\t%1,%0" : "+r"(h) : "rm"(*(const uint64_t *)p));
}