Make redbean StoreAsset() work better

- Better UBSAN error messages
- POSIX Advisory Locks polyfills
- Move redbean manual to /.help.txt
- System call memory safety in ASAN mode
- Character classification now does UNICODE
This commit is contained in:
Justine Tunney 2021-05-14 05:36:58 -07:00
parent 919b6fec10
commit 690be544da
228 changed files with 3653 additions and 3015 deletions

View file

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_LOG_LOG_H_
#define COSMOPOLITAN_LIBC_LOG_LOG_H_
#include "libc/bits/likely.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/winsize.h"
#include "libc/stdio/stdio.h"

View file

@ -133,7 +133,7 @@ relegated static void ShowGeneralRegisters(int fd, ucontext_t *ctx) {
} else {
memset(&st, 0, sizeof(st));
}
dprintf(fd, " %s(%zu) %Lf", "ST", k, st);
dprintf(fd, " %s(%zu) %Lg", "ST", k, st);
++k;
write(fd, "\r\n", 2);
}

View file

@ -34,232 +34,495 @@ __ubsan_get_current_report_data:
.endfn __ubsan_get_current_report_data,globl
__ubsan_handle_type_mismatch_abort:
jmp __ubsan_handle_type_mismatch
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:
jmp __ubsan_handle_float_cast_overflow
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:
__ubsan_handle_type_mismatch_v1_abort:
jmp ___ubsan_handle_type_mismatch_v1
.endfn __ubsan_handle_type_mismatch_v1,globl
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:
nop
// fallthrough
.endfn __ubsan_handle_add_overflow_abort,globl
__ubsan_handle_add_overflow:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "add_overflow",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_alignment_assumption_abort,globl
__ubsan_handle_alignment_assumption:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "alignment_assumption",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_builtin_unreachable_abort,globl
__ubsan_handle_builtin_unreachable:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "builtin_unreachable",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_cfi_bad_type_abort,globl
__ubsan_handle_cfi_bad_type:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "cfi_bad_type",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_cfi_check_fail_abort,globl
__ubsan_handle_cfi_check_fail:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "cfi_check_fail",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_divrem_overflow_abort,globl
__ubsan_handle_divrem_overflow:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "divrem_overflow",si
jmp __ubsan_hop
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:
nop
// fallthrough
.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
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_function_type_mismatch_abort,globl
__ubsan_handle_function_type_mismatch:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "function_type_mismatch",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_implicit_conversion_abort,globl
__ubsan_handle_implicit_conversion:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "implicit_conversion",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_invalid_builtin_abort,globl
__ubsan_handle_invalid_builtin:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "invalid_builtin",si
jmp __ubsan_hop
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:
nop
// fallthrough
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:
loadstr "load_invalid_value (try checking for uninitialized variables)",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_missing_return_abort,globl
__ubsan_handle_missing_return:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "missing_return",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_mul_overflow_abort,globl
__ubsan_handle_mul_overflow:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "mul_overflow",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_negate_overflow_abort,globl
__ubsan_handle_negate_overflow:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "negate_overflow",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_nonnull_arg_abort,globl
__ubsan_handle_nonnull_arg:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "nonnull_arg",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_nonnull_return_v1_abort,globl
__ubsan_handle_nonnull_return_v1:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "nonnull_return_v1",si
jmp __ubsan_hop
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_hop:
jmp __ubsan_abort
.endfn __ubsan_hop
__ubsan_handle_nullability_arg_abort:
nop
// fallthrough
.endfn __ubsan_handle_nullability_arg_abort,globl
__ubsan_handle_nullability_arg:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "nullability_arg",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_nullability_return_v1_abort,globl
__ubsan_handle_nullability_return_v1:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "nullability_return_v1",si
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_pointer_overflow_abort,globl
__ubsan_handle_pointer_overflow:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "pointer_overflow",si
jmp __ubsan_hop
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:
nop
// fallthrough
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_shift_out_of_bounds:
loadstr "shift_out_of_bounds",si
jmp __ubsan_hop
.endfn __ubsan_handle_shift_out_of_bounds,globl
__ubsan_handle_sub_overflow_abort:
nop
// fallthrough
.endfn __ubsan_handle_sub_overflow_abort,globl
__ubsan_handle_sub_overflow:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "sub_overflow",si
jmp __ubsan_hop
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:
nop
// fallthrough
.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
jmp __ubsan_hop
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:
nop
// fallthrough
.endfn __ubsan_handle_nonnull_return_abort,globl
__ubsan_handle_nonnull_return:
push %rbp
mov %rsp,%rbp
.profilable
loadstr "nonnull_return",si
jmp __ubsan_hop
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:
jmp __ubsan_handle_out_of_bounds
push %rbp
mov %rsp,%rbp
.profilable
call __ubsan_handle_out_of_bounds
pop %rbp
ret
.endfn __ubsan_handle_out_of_bounds_abort,globl
.previous

View file

@ -16,6 +16,7 @@
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"
@ -43,6 +44,89 @@ 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;
@ -53,43 +137,73 @@ void __ubsan_abort(const struct UbsanSourceLocation *loc,
}
if (IsDebuggerPresent(false)) DebugBreak();
__start_fatal(loc->file, loc->line);
fprintf(stderr, "%s\r\n", description);
write(2, description, strlen(description));
write(2, "\r\n", 2);
__die();
unreachable;
}
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) {
snprintf(__ubsan_buf, sizeof(__ubsan_buf),
"%s index %,lu into %s out of bounds", info->index_type->name, index,
info->array_type->name);
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);
unreachable;
}
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *type_mismatch,
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
uintptr_t pointer) {
struct UbsanSourceLocation *loc = &type_mismatch->location;
const char *description;
const char *kind = IndexDoubleNulString(kUbsanTypeCheckKinds,
type_mismatch->type_check_kind);
if (pointer == 0) {
description = "null pointer access";
} else if (type_mismatch->alignment != 0 &&
(pointer & (type_mismatch->alignment - 1))) {
description = __ubsan_buf;
snprintf(__ubsan_buf, sizeof(__ubsan_buf), "%s %s %s @%p %s %d",
"unaligned", kind, type_mismatch->type->name, pointer, "align",
type_mismatch->alignment);
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 {
description = __ubsan_buf;
snprintf(__ubsan_buf, sizeof(__ubsan_buf), "%s\r\n\t%s %s %p %s %s",
"insufficient size", kind, "address", pointer,
"with insufficient space for object of type",
type_mismatch->type->name);
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(loc, description);
unreachable;
__ubsan_abort(&info->location, __ubsan_buf);
}
void ___ubsan_handle_type_mismatch_v1(
@ -100,7 +214,6 @@ void ___ubsan_handle_type_mismatch_v1(
mm.alignment = 1u << type_mismatch->log_alignment;
mm.type_check_kind = type_mismatch->type_check_kind;
__ubsan_handle_type_mismatch(&mm, pointer);
unreachable;
}
void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw) {
@ -116,5 +229,4 @@ void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw) {
};
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow");
#endif
unreachable;
}

View file

@ -1,11 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_UBSAN_H_
#define COSMOPOLITAN_LIBC_UBSAN_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/*───────────────────────────────────────────────────────────────────────────│─╗
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;
@ -13,8 +17,8 @@ struct UbsanSourceLocation {
};
struct UbsanTypeDescriptor {
uint16_t kind;
uint16_t info;
uint16_t kind; /* int,float,... */
uint16_t info; /* if int bit 0 if signed, remaining bits are log2(sizeof*8) */
char name[];
};
@ -91,7 +95,7 @@ struct UbsanOutOfBoundsData {
struct UbsanTypeDescriptor *index_type;
};
struct UbsanShiftOutOfBoundsData {
struct UbsanShiftOutOfBoundsInfo {
struct UbsanSourceLocation location;
struct UbsanTypeDescriptor *lhs_type;
struct UbsanTypeDescriptor *rhs_type;