[compiler-rt] a11cb10 - [dfsan] Add function that prints origin stack trace to buffer
George Balatsouras via llvm-commits
llvm-commits at lists.llvm.org
Mon May 24 11:09:24 PDT 2021
Author: George Balatsouras
Date: 2021-05-24T11:09:03-07:00
New Revision: a11cb10a3691ea569ab3390052cfec48ce350f27
URL: https://github.com/llvm/llvm-project/commit/a11cb10a3691ea569ab3390052cfec48ce350f27
DIFF: https://github.com/llvm/llvm-project/commit/a11cb10a3691ea569ab3390052cfec48ce350f27.diff
LOG: [dfsan] Add function that prints origin stack trace to buffer
Reviewed By: stephan.yichao.zhao
Differential Revision: https://reviews.llvm.org/D102451
Added:
Modified:
compiler-rt/include/sanitizer/dfsan_interface.h
compiler-rt/lib/dfsan/dfsan.cpp
compiler-rt/lib/dfsan/done_abilist.txt
compiler-rt/test/dfsan/origin_stack_trace.c
Removed:
################################################################################
diff --git a/compiler-rt/include/sanitizer/dfsan_interface.h b/compiler-rt/include/sanitizer/dfsan_interface.h
index 40f9379b5579c..34b0b6378d653 100644
--- a/compiler-rt/include/sanitizer/dfsan_interface.h
+++ b/compiler-rt/include/sanitizer/dfsan_interface.h
@@ -123,6 +123,43 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
/// on, or the address is not labeled, it prints nothing.
void dfsan_print_origin_trace(const void *addr, const char *description);
+/// 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
+/// not labeled, it prints nothing.
+///
+/// Typical usage:
+/// \code
+/// char kDescription[] = "...";
+/// char buf[1024];
+/// dfsan_sprint_origin_trace(&tainted_var, kDescription, buf, sizeof(buf));
+/// \endcode
+///
+/// Typical usage that handles truncation:
+/// \code
+/// char buf[1024];
+/// int len = dfsan_sprint_origin_trace(&var, nullptr, buf, sizeof(buf));
+///
+/// if (len < sizeof(buf)) {
+/// ProcessOriginTrace(tmpbuf);
+/// else {
+/// char *tmpbuf = new char[len + 1];
+/// dfsan_sprint_origin_trace(&var, nullptr, tmpbuf, len + 1);
+/// ProcessOriginTrace(tmpbuf);
+/// delete[] tmpbuf;
+/// }
+/// \endcode
+///
+/// \param addr The tainted memory address whose origin we are printing.
+/// \param description A description printed at the beginning of the trace.
+/// \param [out] out_buf The output buffer to write the results to.
+/// \param out_buf_size The size of \p out_buf.
+///
+/// \returns The number of symbols that should have been written to \p out_buf
+/// (not including trailing null byte '\0'). Thus, the string is truncated iff
+/// 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);
+
/// Retrieves the very first origin associated with the data at the given
/// address.
dfsan_origin dfsan_get_init_origin(const void *addr);
diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp
index fb162e22f6b74..124ff97b03b3f 100644
--- a/compiler-rt/lib/dfsan/dfsan.cpp
+++ b/compiler-rt/lib/dfsan/dfsan.cpp
@@ -842,49 +842,123 @@ class Decorator : public __sanitizer::SanitizerCommonDecorator {
const char *Origin() const { return Magenta(); }
};
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace(
- const void *addr, const char *description) {
+namespace {
+
+void PrintNoOriginTrackingWarning() {
Decorator d;
+ Printf(
+ " %sDFSan: origin tracking is not enabled. Did you specify the "
+ "-dfsan-track-origins=1 option?%s\n",
+ d.Warning(), d.Default());
+}
- if (!__dfsan_get_track_origins()) {
- Printf(
- " %sDFSan: origin tracking is not enabled. Did you specify the "
- "-dfsan-track-origins=1 option?%s\n",
- d.Warning(), d.Default());
- return;
- }
+void PrintNoTaintWarning(const void *address) {
+ Decorator d;
+ Printf(" %sDFSan: no tainted value at %x%s\n", d.Warning(), address,
+ d.Default());
+}
+
+void PrintInvalidOriginWarning(dfsan_label label, const void *address) {
+ Decorator d;
+ Printf(
+ " %sTaint value 0x%x (at %p) has invalid origin tracking. This can "
+ "be a DFSan bug.%s\n",
+ d.Warning(), label, address, d.Default());
+}
+
+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);
- if (!label) {
- Printf(" %sDFSan: no tainted value at %x%s\n", d.Warning(), addr,
- d.Default());
- return;
- }
+ CHECK(label);
const dfsan_origin origin = *__dfsan::origin_for(addr);
- Printf(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n", d.Origin(),
- label, addr, description ? description : "", d.Default());
+ 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 found = false;
+
while (o.isChainedOrigin()) {
StackTrace stack;
dfsan_origin origin_id = o.raw_id();
o = o.getNextChainedOrigin(&stack);
if (o.isChainedOrigin())
- Printf(" %sOrigin value: 0x%x, Taint value was stored to memory at%s\n",
- d.Origin(), origin_id, d.Default());
+ out->append(
+ " %sOrigin value: 0x%x, Taint value was stored to memory at%s\n",
+ d.Origin(), origin_id, d.Default());
else
- Printf(" %sOrigin value: 0x%x, Taint value was created at%s\n",
- d.Origin(), origin_id, d.Default());
- stack.Print();
+ out->append(" %sOrigin value: 0x%x, Taint value was created at%s\n",
+ d.Origin(), origin_id, d.Default());
+
+ // Includes a trailing newline, so no need to add it again.
+ stack.PrintTo(out);
found = true;
}
- if (!found)
- Printf(
- " %sTaint value 0x%x (at %p) has invalid origin tracking. This can "
- "be a DFSan bug.%s\n",
- d.Warning(), label, addr, d.Default());
+
+ return found;
+}
+
+} // namespace
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace(
+ const void *addr, const char *description) {
+ if (!__dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return;
+ }
+
+ const dfsan_label label = *__dfsan::shadow_for(addr);
+ if (!label) {
+ PrintNoTaintWarning(addr);
+ return;
+ }
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceToStr(addr, description, &trace);
+
+ if (trace.length())
+ Printf("%s", trace.data());
+
+ if (!success)
+ PrintInvalidOriginWarning(label, addr);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE size_t
+dfsan_sprint_origin_trace(const void *addr, const char *description,
+ char *out_buf, size_t out_buf_size) {
+ CHECK(out_buf);
+
+ if (!__dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return 0;
+ }
+
+ const dfsan_label label = *__dfsan::shadow_for(addr);
+ if (!label) {
+ PrintNoTaintWarning(addr);
+ return 0;
+ }
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceToStr(addr, description, &trace);
+
+ if (!success) {
+ PrintInvalidOriginWarning(label, addr);
+ 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
diff --git a/compiler-rt/lib/dfsan/done_abilist.txt b/compiler-rt/lib/dfsan/done_abilist.txt
index d41ee33203c91..9694af0b95fb4 100644
--- a/compiler-rt/lib/dfsan/done_abilist.txt
+++ b/compiler-rt/lib/dfsan/done_abilist.txt
@@ -30,6 +30,8 @@ fun:dfsan_flush=uninstrumented
fun:dfsan_flush=discard
fun:dfsan_print_origin_trace=uninstrumented
fun:dfsan_print_origin_trace=discard
+fun:dfsan_sprint_origin_trace=uninstrumented
+fun:dfsan_sprint_origin_trace=discard
fun:dfsan_get_origin=uninstrumented
fun:dfsan_get_origin=custom
fun:dfsan_get_init_origin=uninstrumented
diff --git a/compiler-rt/test/dfsan/origin_stack_trace.c b/compiler-rt/test/dfsan/origin_stack_trace.c
index 40a51e374fd14..c7018a54d7215 100644
--- a/compiler-rt/test/dfsan/origin_stack_trace.c
+++ b/compiler-rt/test/dfsan/origin_stack_trace.c
@@ -1,14 +1,16 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
// RUN: %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK < %t.out
+// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK < %t.out
+// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch
#include <sanitizer/dfsan_interface.h>
+#include <stdio.h>
+#include <string.h>
#define NOINLINE __attribute__((noinline))
@@ -32,13 +34,67 @@ int main(int argc, char *argv[]) {
baz(8, &a, sizeof(a));
int c = foo(a, b);
dfsan_print_origin_trace(&c, NULL);
-}
+ // CHECK: Taint value 0x1 {{.*}} origin tracking ()
+ // CHECK: Origin value: {{.*}}, Taint value was stored to memory at
+ // CHECK: #0 {{.*}} in main {{.*}}origin_stack_trace.c:[[@LINE-4]]
+
+ // CHECK: Origin value: {{.*}}, Taint value was created at
+ // CHECK: #0 {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-19]]
+ // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-22]]
+ // CHECK: #9 {{.*}} in dfs$baz {{.*}}origin_stack_trace.c:[[@LINE-16]]
+
+ char buf[3000];
+ size_t length = dfsan_sprint_origin_trace(&c, NULL, buf, sizeof(buf));
+
+ printf("==OUTPUT==\n\n%s==EOS==\n", buf);
+ // CHECK: ==OUTPUT==
+ // CHECK: Taint value 0x1 {{.*}} origin tracking ()
+ // CHECK: Origin value: {{.*}}, Taint value was stored to memory at
+ // CHECK: #0 {{.*}} in main {{.*}}origin_stack_trace.c:[[@LINE-18]]
+
+ // CHECK: Origin value: {{.*}}, Taint value was created at
+ // CHECK: #0 {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-33]]
+ // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-36]]
+ // CHECK: #9 {{.*}} in dfs$baz {{.*}}origin_stack_trace.c:[[@LINE-30]]
+ // CHECK: ==EOS==
+
+ char tinybuf[18];
+ size_t same_length = dfsan_sprint_origin_trace(&c, NULL, tinybuf, sizeof(tinybuf));
+
+ printf("==TRUNCATED OUTPUT==\n\n%s==EOS==\n", tinybuf);
+ // CHECK: ==TRUNCATED OUTPUT==
+ // CHECK: Taint value 0x1==EOS==
-// CHECK: Taint value 0x1 {{.*}} origin tracking ()
-// CHECK: Origin value: {{.*}}, Taint value was stored to memory at
-// CHECK: #0 {{.*}} in main {{.*}}origin_stack_trace.c:[[@LINE-6]]
+ printf("Returned length: %zu\n", length);
+ printf("Actual length: %zu\n", strlen(buf));
+ printf("Returned length with truncation: %zu\n", same_length);
-// CHECK: Origin value: {{.*}}, Taint value was created at
-// CHECK: #0 {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-21]]
-// CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-24]]
-// CHECK: #9 {{.*}} in dfs$baz {{.*}}origin_stack_trace.c:[[@LINE-18]]
+ // CHECK: Returned length: [[#LEN:]]
+ // CHECK: Actual length: [[#LEN]]
+ // CHECK: Returned length with truncation: [[#LEN]]
+
+ size_t length_with_desc = dfsan_sprint_origin_trace(&c, "DESCRIPTION", buf, sizeof(buf));
+
+ printf("==OUTPUT==\n\n%s==EOS==\n", buf);
+ // CHECK: ==OUTPUT==
+ // CHECK: Taint value 0x1 {{.*}} origin tracking (DESCRIPTION)
+ // CHECK: Origin value: {{.*}}, Taint value was stored to memory at
+ // CHECK: #0 {{.*}} in main {{.*}}origin_stack_trace.c:[[@LINE-47]]
+
+ // CHECK: Origin value: {{.*}}, Taint value was created at
+ // CHECK: #0 {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-62]]
+ // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in dfs$bar {{.*}}origin_stack_trace.c:[[@LINE-65]]
+ // CHECK: #9 {{.*}} in dfs$baz {{.*}}origin_stack_trace.c:[[@LINE-59]]
+ // CHECK: ==EOS==
+
+ printf("Returned length: %zu\n", length_with_desc);
+ // COMM: Message length is increased by 11: the length of "DESCRIPTION".
+ // CHECK: Returned length: [[#LEN + 11]]
+
+ buf[0] = '\0';
+ length = dfsan_sprint_origin_trace(&c, NULL, buf, 0);
+ printf("Output=\"%s\"\n", buf);
+ printf("Returned length: %zu\n", length);
+ // CHECK: Output=""
+ // CHECK: Returned length: [[#LEN]]
+}
More information about the llvm-commits
mailing list