aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/include/sanitizer/dfsan_interface.h7
-rw-r--r--compiler-rt/lib/dfsan/dfsan.cpp85
-rw-r--r--compiler-rt/lib/dfsan/done_abilist.txt4
-rw-r--r--compiler-rt/test/dfsan/origin_id_stack_trace.c74
4 files changed, 156 insertions, 14 deletions
diff --git a/compiler-rt/include/sanitizer/dfsan_interface.h b/compiler-rt/include/sanitizer/dfsan_interface.h
index d6209a3..769aecf 100644
--- a/compiler-rt/include/sanitizer/dfsan_interface.h
+++ b/compiler-rt/include/sanitizer/dfsan_interface.h
@@ -87,6 +87,9 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
/// prints description at the beginning of the trace. If origin tracking is not
/// on, or the address is not labeled, it prints nothing.
void dfsan_print_origin_trace(const void *addr, const char *description);
+/// As above, but use an origin id from dfsan_get_origin() instead of address.
+/// Does not include header line with taint label and address information.
+void dfsan_print_origin_id_trace(dfsan_origin origin);
/// Prints the origin trace of the label at the address \p addr to a
/// pre-allocated output buffer. If origin tracking is not on, or the address is
@@ -124,6 +127,10 @@ void dfsan_print_origin_trace(const void *addr, const char *description);
/// return value is not less than \p out_buf_size.
size_t dfsan_sprint_origin_trace(const void *addr, const char *description,
char *out_buf, size_t out_buf_size);
+/// As above, but use an origin id from dfsan_get_origin() instead of address.
+/// Does not include header line with taint label and address information.
+size_t dfsan_sprint_origin_id_trace(dfsan_origin origin, char *out_buf,
+ size_t out_buf_size);
/// Prints the stack trace leading to this call to a pre-allocated output
/// buffer.
diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp
index ce2c04d..ee7221c 100644
--- a/compiler-rt/lib/dfsan/dfsan.cpp
+++ b/compiler-rt/lib/dfsan/dfsan.cpp
@@ -630,22 +630,16 @@ void PrintInvalidOriginWarning(dfsan_label label, const void *address) {
d.Warning(), label, address, d.Default());
}
-bool PrintOriginTraceToStr(const void *addr, const char *description,
- InternalScopedString *out) {
- CHECK(out);
- CHECK(dfsan_get_track_origins());
+void PrintInvalidOriginIdWarning(dfsan_origin origin) {
Decorator d;
+ Printf(
+ " %sOrigin Id %d has invalid origin tracking. This can "
+ "be a DFSan bug.%s\n",
+ d.Warning(), origin, d.Default());
+}
- const dfsan_label label = *__dfsan::shadow_for(addr);
- CHECK(label);
-
- const dfsan_origin origin = *__dfsan::origin_for(addr);
-
- out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n",
- d.Origin(), label, addr, description ? description : "",
- d.Default());
-
- Origin o = Origin::FromRawId(origin);
+bool PrintOriginTraceFramesToStr(Origin o, InternalScopedString *out) {
+ Decorator d;
bool found = false;
while (o.isChainedOrigin()) {
@@ -668,6 +662,25 @@ bool PrintOriginTraceToStr(const void *addr, const char *description,
return found;
}
+bool PrintOriginTraceToStr(const void *addr, const char *description,
+ InternalScopedString *out) {
+ CHECK(out);
+ CHECK(dfsan_get_track_origins());
+ Decorator d;
+
+ const dfsan_label label = *__dfsan::shadow_for(addr);
+ CHECK(label);
+
+ const dfsan_origin origin = *__dfsan::origin_for(addr);
+
+ out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n",
+ d.Origin(), label, addr, description ? description : "",
+ d.Default());
+
+ Origin o = Origin::FromRawId(origin);
+ return PrintOriginTraceFramesToStr(o, out);
+}
+
} // namespace
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace(
@@ -725,6 +738,50 @@ dfsan_sprint_origin_trace(const void *addr, const char *description,
return trace.length();
}
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_id_trace(
+ dfsan_origin origin) {
+ if (!dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return;
+ }
+ Origin o = Origin::FromRawId(origin);
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceFramesToStr(o, &trace);
+
+ if (trace.length())
+ Printf("%s", trace.data());
+
+ if (!success)
+ PrintInvalidOriginIdWarning(origin);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr dfsan_sprint_origin_id_trace(
+ dfsan_origin origin, char *out_buf, uptr out_buf_size) {
+ CHECK(out_buf);
+
+ if (!dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return 0;
+ }
+ Origin o = Origin::FromRawId(origin);
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceFramesToStr(o, &trace);
+
+ if (!success) {
+ PrintInvalidOriginIdWarning(origin);
+ return 0;
+ }
+
+ if (out_buf_size) {
+ internal_strncpy(out_buf, trace.data(), out_buf_size - 1);
+ out_buf[out_buf_size - 1] = '\0';
+ }
+
+ return trace.length();
+}
+
extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
dfsan_get_init_origin(const void *addr) {
if (!dfsan_get_track_origins())
diff --git a/compiler-rt/lib/dfsan/done_abilist.txt b/compiler-rt/lib/dfsan/done_abilist.txt
index eef7c48..b944b79 100644
--- a/compiler-rt/lib/dfsan/done_abilist.txt
+++ b/compiler-rt/lib/dfsan/done_abilist.txt
@@ -30,8 +30,12 @@ fun:dfsan_flush=uninstrumented
fun:dfsan_flush=discard
fun:dfsan_print_origin_trace=uninstrumented
fun:dfsan_print_origin_trace=discard
+fun:dfsan_print_origin_id_trace=uninstrumented
+fun:dfsan_print_origin_id_trace=discard
fun:dfsan_sprint_origin_trace=uninstrumented
fun:dfsan_sprint_origin_trace=discard
+fun:dfsan_sprint_origin_id_trace=uninstrumented
+fun:dfsan_sprint_origin_id_trace=discard
fun:dfsan_sprint_stack_trace=uninstrumented
fun:dfsan_sprint_stack_trace=discard
fun:dfsan_get_origin=uninstrumented
diff --git a/compiler-rt/test/dfsan/origin_id_stack_trace.c b/compiler-rt/test/dfsan/origin_id_stack_trace.c
new file mode 100644
index 0000000..5958a8a
--- /dev/null
+++ b/compiler-rt/test/dfsan/origin_id_stack_trace.c
@@ -0,0 +1,74 @@
+// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
+// RUN: %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+//
+// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
+// RUN: %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+//
+// REQUIRES: x86_64-target-arch
+
+#include <sanitizer/dfsan_interface.h>
+#include <stdio.h>
+#include <string.h>
+
+__attribute__((noinline)) int foo(int a, int b) { return a + b; }
+
+__attribute__((noinline)) void bar(int depth, void *addr, int size) {
+ if (depth) {
+ bar(depth - 1, addr, size);
+ } else {
+ dfsan_set_label(1, addr, size);
+ }
+}
+
+__attribute__((noinline)) void baz(int depth, void *addr, int size) {
+ bar(depth, addr, size);
+}
+
+int main(int argc, char *argv[]) {
+ int a = 10;
+ int b = 20;
+ baz(8, &a, sizeof(a));
+ int c = foo(a, b);
+ dfsan_origin c_o = dfsan_get_origin(c);
+ dfsan_print_origin_id_trace(c_o);
+ // CHECK: Origin value: {{.*}}, Taint value was created at
+ // CHECK: #0 {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-16]]
+ // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-19]]
+ // CHECK: #9 {{.*}} in baz.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-13]]
+
+ char buf[3000];
+ size_t length = dfsan_sprint_origin_id_trace(c_o, buf, sizeof(buf));
+
+ printf("==OUTPUT==\n\n%s==EOS==\n", buf);
+ // CHECK: ==OUTPUT==
+ // CHECK: Origin value: {{.*}}, Taint value was created at
+ // CHECK: #0 {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-26]]
+ // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-29]]
+ // CHECK: #9 {{.*}} in baz.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-23]]
+ // CHECK: ==EOS==
+
+ char tinybuf[20];
+ size_t same_length =
+ dfsan_sprint_origin_id_trace(c_o, tinybuf, sizeof(tinybuf));
+
+ printf("==TRUNCATED OUTPUT==\n\n%s==EOS==\n", tinybuf);
+ // CHECK: ==TRUNCATED OUTPUT==
+ // CHECK: Origin value: 0x1==EOS==
+
+ printf("Returned length: %zu\n", length);
+ printf("Actual length: %zu\n", strlen(buf));
+ printf("Returned length with truncation: %zu\n", same_length);
+
+ // CHECK: Returned length: [[#LEN:]]
+ // CHECK: Actual length: [[#LEN]]
+ // CHECK: Returned length with truncation: [[#LEN]]
+
+ buf[0] = '\0';
+ length = dfsan_sprint_origin_id_trace(c_o, buf, 0);
+ printf("Output=\"%s\"\n", buf);
+ printf("Returned length: %zu\n", length);
+ // CHECK: Output=""
+ // CHECK: Returned length: [[#LEN]]
+}