[ubsan-minimal] Report the address of an error
This implements a FIXME in the runtime library and adds printing the address at the end of the message as "by 0x123abc". The buffer for the message is allocated on the stack in a handler, so the stack memory consumption is slightly increased. No additional external dependencies are added. Differential revision: https://reviews.llvm.org/D131914
This commit is contained in:
parent
408ebe5e3a
commit
84c4efbc6d
|
@ -51,6 +51,19 @@ __attribute__((noinline)) static bool report_this_error(uintptr_t caller) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((noinline)) static void decorate_msg(char *buf,
|
||||||
|
uintptr_t caller) {
|
||||||
|
// print the address by nibbles
|
||||||
|
for (unsigned shift = sizeof(uintptr_t) * 8; shift;) {
|
||||||
|
shift -= 4;
|
||||||
|
unsigned nibble = (caller >> shift) & 0xf;
|
||||||
|
*(buf++) = nibble < 10 ? nibble + '0' : nibble - 10 + 'a';
|
||||||
|
}
|
||||||
|
// finish the message
|
||||||
|
buf[0] = '\n';
|
||||||
|
buf[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
extern "C" __attribute__((weak)) void android_set_abort_message(const char *);
|
extern "C" __attribute__((weak)) void android_set_abort_message(const char *);
|
||||||
static void abort_with_message(const char *msg) {
|
static void abort_with_message(const char *msg) {
|
||||||
|
@ -76,18 +89,28 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
|
||||||
|
|
||||||
#define INTERFACE extern "C" __attribute__((visibility("default")))
|
#define INTERFACE extern "C" __attribute__((visibility("default")))
|
||||||
|
|
||||||
// FIXME: add caller pc to the error message (possibly as "ubsan: error-type
|
// How many chars we need to reserve to print an address.
|
||||||
// @1234ABCD").
|
constexpr unsigned kAddrBuf = SANITIZER_WORDSIZE / 4;
|
||||||
|
#define MSG_TMPL(msg) "ubsan: " msg " by 0x"
|
||||||
|
#define MSG_TMPL_END(buf, msg) (buf + sizeof(MSG_TMPL(msg)) - 1)
|
||||||
|
// Reserve an additional byte for '\n'.
|
||||||
|
#define MSG_BUF_LEN(msg) (sizeof(MSG_TMPL(msg)) + kAddrBuf + 1)
|
||||||
|
|
||||||
#define HANDLER_RECOVER(name, msg) \
|
#define HANDLER_RECOVER(name, msg) \
|
||||||
INTERFACE void __ubsan_handle_##name##_minimal() { \
|
INTERFACE void __ubsan_handle_##name##_minimal() { \
|
||||||
if (!report_this_error(GET_CALLER_PC())) return; \
|
uintptr_t caller = GET_CALLER_PC(); \
|
||||||
message("ubsan: " msg "\n"); \
|
if (!report_this_error(caller)) return; \
|
||||||
|
char msg_buf[MSG_BUF_LEN(msg)] = MSG_TMPL(msg); \
|
||||||
|
decorate_msg(MSG_TMPL_END(msg_buf, msg), caller); \
|
||||||
|
message(msg_buf); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HANDLER_NORECOVER(name, msg) \
|
#define HANDLER_NORECOVER(name, msg) \
|
||||||
INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
|
INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
|
||||||
message("ubsan: " msg "\n"); \
|
char msg_buf[MSG_BUF_LEN(msg)] = MSG_TMPL(msg); \
|
||||||
abort_with_message("ubsan: " msg); \
|
decorate_msg(MSG_TMPL_END(msg_buf, msg), GET_CALLER_PC()); \
|
||||||
|
message(msg_buf); \
|
||||||
|
abort_with_message(msg_buf); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HANDLER(name, msg) \
|
#define HANDLER(name, msg) \
|
||||||
|
|
|
@ -8,7 +8,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
void *t = __builtin_assume_aligned(ptr + 1, 0x8000);
|
void *t = __builtin_assume_aligned(ptr + 1, 0x8000);
|
||||||
(void)t;
|
(void)t;
|
||||||
// CHECK: ubsan: alignment-assumption
|
// CHECK: ubsan: alignment-assumption by 0x{{[[:xdigit:]]+$}}
|
||||||
// CHECK-NOT: alignment-assumption
|
// CHECK-NOT: alignment-assumption
|
||||||
|
|
||||||
free(ptr);
|
free(ptr);
|
||||||
|
|
|
@ -10,7 +10,7 @@ int main() {
|
||||||
|
|
||||||
// Positive tests.
|
// Positive tests.
|
||||||
int32_t t0 = (~((uint32_t)0));
|
int32_t t0 = (~((uint32_t)0));
|
||||||
// CHECK: implicit-conversion
|
// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
|
||||||
// CHECK-NOT: implicit-conversion
|
// CHECK-NOT: implicit-conversion
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -10,7 +10,7 @@ int main() {
|
||||||
|
|
||||||
// Positive tests.
|
// Positive tests.
|
||||||
int8_t t0 = (uint32_t)-1;
|
int8_t t0 = (uint32_t)-1;
|
||||||
// CHECK: implicit-conversion
|
// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
|
||||||
// CHECK-NOT: implicit-conversion
|
// CHECK-NOT: implicit-conversion
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -18,7 +18,7 @@ int main() {
|
||||||
|
|
||||||
// Positive tests.
|
// Positive tests.
|
||||||
uint8_t t0 = (int32_t)(-1);
|
uint8_t t0 = (int32_t)(-1);
|
||||||
// CHECK: implicit-conversion
|
// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
|
||||||
// CHECK-NOT: implicit-conversion
|
// CHECK-NOT: implicit-conversion
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -18,7 +18,7 @@ int main() {
|
||||||
|
|
||||||
// Positive tests.
|
// Positive tests.
|
||||||
uint8_t t0 = (~((uint32_t)(0)));
|
uint8_t t0 = (~((uint32_t)(0)));
|
||||||
// CHECK: implicit-conversion
|
// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
|
||||||
// CHECK-NOT: implicit-conversion
|
// CHECK-NOT: implicit-conversion
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -8,16 +8,16 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
base = (char *)0;
|
base = (char *)0;
|
||||||
result = base + 0;
|
result = base + 0;
|
||||||
// CHECK-C: pointer-overflow
|
// CHECK-C: pointer-overflow by 0x{{[[:xdigit:]]+$}}
|
||||||
// CHECK-CPP-NOT: pointer-overflow
|
// CHECK-CPP-NOT: pointer-overflow
|
||||||
|
|
||||||
base = (char *)0;
|
base = (char *)0;
|
||||||
result = base + 1;
|
result = base + 1;
|
||||||
// CHECK: pointer-overflow
|
// CHECK: pointer-overflow by 0x{{[[:xdigit:]]+$}}
|
||||||
|
|
||||||
base = (char *)1;
|
base = (char *)1;
|
||||||
result = base - 1;
|
result = base - 1;
|
||||||
// CHECK: pointer-overflow
|
// CHECK: pointer-overflow by 0x{{[[:xdigit:]]+$}}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,25 +4,25 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int *_Nonnull h() {
|
int *_Nonnull h() {
|
||||||
// CHECK: nullability-return
|
// CHECK: nullability-return by 0x{{[[:xdigit:]]+$}}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((returns_nonnull))
|
__attribute__((returns_nonnull))
|
||||||
int *i() {
|
int *i() {
|
||||||
// CHECK: nonnull-return
|
// CHECK: nonnull-return by 0x{{[[:xdigit:]]+$}}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
int f(int x, int y) {
|
int f(int x, int y) {
|
||||||
// CHECK: mul-overflow
|
// CHECK: mul-overflow by 0x{{[[:xdigit:]]+$}}
|
||||||
return x * y;
|
return x * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
int g(int x, int y) {
|
int g(int x, int y) {
|
||||||
// CHECK: mul-overflow
|
// CHECK: mul-overflow by 0x{{[[:xdigit:]]+$}}
|
||||||
return x * (y + 1);
|
return x * (y + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
int main() {
|
int main() {
|
||||||
uint32_t k = 0x87654321;
|
uint32_t k = 0x87654321;
|
||||||
k += 0xedcba987;
|
k += 0xedcba987;
|
||||||
// CHECK: add-overflow
|
// CHECK: add-overflow by 0x{{[[:xdigit:]]+$}}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue