[ubsan-minimal] Report the address of an error
authorIgor Kudrin <ikudrin@accesssoftek.com>
Mon, 15 Aug 2022 18:24:08 +0000 (22:24 +0400)
committerIgor Kudrin <ikudrin@accesssoftek.com>
Mon, 5 Sep 2022 10:18:25 +0000 (14:18 +0400)
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

compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
compiler-rt/test/ubsan_minimal/TestCases/alignment-assumption.c
compiler-rt/test/ubsan_minimal/TestCases/implicit-integer-sign-change.c
compiler-rt/test/ubsan_minimal/TestCases/implicit-signed-integer-truncation-or-sign-change.c
compiler-rt/test/ubsan_minimal/TestCases/implicit-signed-integer-truncation.c
compiler-rt/test/ubsan_minimal/TestCases/implicit-unsigned-integer-truncation.c
compiler-rt/test/ubsan_minimal/TestCases/nullptr-and-nonzero-offset.c
compiler-rt/test/ubsan_minimal/TestCases/recover-dedup.cpp
compiler-rt/test/ubsan_minimal/TestCases/uadd-overflow.cpp

index 5301a51..53a3273 100644 (file)
@@ -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__)
 extern "C" __attribute__((weak)) void android_set_abort_message(const char *);
 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")))
 
-// FIXME: add caller pc to the error message (possibly as "ubsan: error-type
-// @1234ABCD").
+// How many chars we need to reserve to print an address.
+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)                               \
   INTERFACE void __ubsan_handle_##name##_minimal() {             \
-    if (!report_this_error(GET_CALLER_PC())) return; \
-    message("ubsan: " msg "\n");                                 \
+    uintptr_t caller = GET_CALLER_PC();                  \
+    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)                             \
   INTERFACE void __ubsan_handle_##name##_minimal_abort() {       \
-    message("ubsan: " msg "\n");                                 \
-    abort_with_message("ubsan: " msg);                           \
+    char msg_buf[MSG_BUF_LEN(msg)] = MSG_TMPL(msg);              \
+    decorate_msg(MSG_TMPL_END(msg_buf, msg), GET_CALLER_PC());   \
+    message(msg_buf);                                            \
+    abort_with_message(msg_buf);                                 \
   }
 
 #define HANDLER(name, msg)                                       \
index 08696c8..acc3e85 100644 (file)
@@ -8,7 +8,7 @@ int main(int argc, char *argv[]) {
 
   void *t = __builtin_assume_aligned(ptr + 1, 0x8000);
   (void)t;
-  // CHECK: ubsan: alignment-assumption
+  // CHECK: ubsan: alignment-assumption by 0x{{[[:xdigit:]]+$}}
   // CHECK-NOT: alignment-assumption
 
   free(ptr);
index 1e20892..0f1bbbf 100644 (file)
@@ -10,7 +10,7 @@ int main() {
 
   // Positive tests.
   int32_t t0 = (~((uint32_t)0));
-// CHECK: implicit-conversion
+// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
 // CHECK-NOT: implicit-conversion
 
   return 0;
index 3a72a40..e9f26dd 100644 (file)
@@ -10,7 +10,7 @@ int main() {
 
   // Positive tests.
   int8_t t0 = (uint32_t)-1;
-// CHECK: implicit-conversion
+// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
 // CHECK-NOT: implicit-conversion
 
   return 0;
index 9677407..dc8d775 100644 (file)
@@ -18,7 +18,7 @@ int main() {
 
   // Positive tests.
   uint8_t t0 = (int32_t)(-1);
-// CHECK: implicit-conversion
+// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
 // CHECK-NOT: implicit-conversion
 
   return 0;
index 8b9e166..77d38f5 100644 (file)
@@ -18,7 +18,7 @@ int main() {
 
   // Positive tests.
   uint8_t t0 = (~((uint32_t)(0)));
-// CHECK: implicit-conversion
+// CHECK: implicit-conversion by 0x{{[[:xdigit:]]+$}}
 // CHECK-NOT: implicit-conversion
 
   return 0;
index 699aeee..2077e7d 100644 (file)
@@ -8,16 +8,16 @@ int main(int argc, char *argv[]) {
 
   base = (char *)0;
   result = base + 0;
-  // CHECK-C: pointer-overflow
+  // CHECK-C: pointer-overflow by 0x{{[[:xdigit:]]+$}}
   // CHECK-CPP-NOT: pointer-overflow
 
   base = (char *)0;
   result = base + 1;
-  // CHECK: pointer-overflow
+  // CHECK: pointer-overflow by 0x{{[[:xdigit:]]+$}}
 
   base = (char *)1;
   result = base - 1;
-  // CHECK: pointer-overflow
+  // CHECK: pointer-overflow by 0x{{[[:xdigit:]]+$}}
 
   return 0;
 }
index 4dfd699..b7c9ddc 100644 (file)
@@ -4,25 +4,25 @@
 #include <stdio.h>
 
 int *_Nonnull h() {
-  // CHECK: nullability-return
+  // CHECK: nullability-return by 0x{{[[:xdigit:]]+$}}
   return NULL;
 }
 
 __attribute__((returns_nonnull))
 int *i() {
-  // CHECK: nonnull-return
+  // CHECK: nonnull-return by 0x{{[[:xdigit:]]+$}}
   return NULL;
 }
 
 __attribute__((noinline))
 int f(int x, int y) {
-  // CHECK: mul-overflow
+  // CHECK: mul-overflow by 0x{{[[:xdigit:]]+$}}
   return x * y;
 }
 
 __attribute__((noinline))
 int g(int x, int y) {
-  // CHECK: mul-overflow
+  // CHECK: mul-overflow by 0x{{[[:xdigit:]]+$}}
   return x * (y + 1);
 }
 
index 0345750..4ae081c 100644 (file)
@@ -6,5 +6,5 @@
 int main() {
   uint32_t k = 0x87654321;
   k += 0xedcba987;
-  // CHECK: add-overflow
+  // CHECK: add-overflow by 0x{{[[:xdigit:]]+$}}
 }