mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 08:18:30 +00:00
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:
parent
d5ff2c3fb9
commit
5e8ae2d5bc
80 changed files with 506 additions and 249 deletions
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue