[compiler-rt] d5617ad - [compiler-rt][nsan] Add more tests for shadow memory (#100906)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 19 10:44:56 PDT 2024


Author: Alexander Shaposhnikov
Date: 2024-08-19T10:44:53-07:00
New Revision: d5617ada36705e871f329a7b0efb19ce6e6e2a1f

URL: https://github.com/llvm/llvm-project/commit/d5617ada36705e871f329a7b0efb19ce6e6e2a1f
DIFF: https://github.com/llvm/llvm-project/commit/d5617ada36705e871f329a7b0efb19ce6e6e2a1f.diff

LOG: [compiler-rt][nsan] Add more tests for shadow memory (#100906)

Add more tests for shadow memory.

Added: 
    compiler-rt/test/nsan/stable_sort.cpp
    compiler-rt/test/nsan/swap.cpp

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/compiler-rt/test/nsan/stable_sort.cpp b/compiler-rt/test/nsan/stable_sort.cpp
new file mode 100644
index 00000000000000..d280eedf0ebf7b
--- /dev/null
+++ b/compiler-rt/test/nsan/stable_sort.cpp
@@ -0,0 +1,56 @@
+// RUN: %clangxx_nsan -O2 -g %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// Check compilation mode that is required to call memcpy/memmove.
+// RUN: %clangxx_nsan -fno-builtin -O2 -g %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// This tests a particularaly hard case of memory tracking. stable_sort does
+// conditional swaps of pairs of elements with mixed types (int/double).
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdio>
+#include <utility>
+#include <vector>
+
+extern "C" void __nsan_dump_shadow_mem(const char *addr, size_t size_bytes,
+                                       size_t bytes_per_line, size_t reserved);
+
+__attribute__((noinline)) void Run(std::vector<int> &indices,
+                                   std::vector<double> &values) {
+  const auto num_entries = indices.size();
+  std::vector<std::pair<int, double>> entries;
+  entries.reserve(num_entries);
+  for (size_t i = 0; i < num_entries; ++i)
+    entries.emplace_back(indices[i], values[i]);
+
+  __nsan_dump_shadow_mem((const char *)&entries[0].second, sizeof(double),
+                         sizeof(double), 0);
+  __nsan_dump_shadow_mem((const char *)&entries[1].second, sizeof(double),
+                         sizeof(double), 0);
+  // CHECK: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (1.02800000000000002487)
+  // CHECK-NEXT: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (7.95099999999999962341)
+  std::stable_sort(
+      entries.begin(), entries.end(),
+      [](const std::pair<int, double> &a, const std::pair<int, double> &b) {
+        return a.first < b.first;
+      });
+  __nsan_dump_shadow_mem((const char *)&entries[0].second, sizeof(double),
+                         sizeof(double), 0);
+  __nsan_dump_shadow_mem((const char *)&entries[1].second, sizeof(double),
+                         sizeof(double), 0);
+  // We make sure that the shadow values have been swapped correctly.
+  // CHECK-NEXT: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (7.95099999999999962341)
+  // CHECK-NEXT: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (1.02800000000000002487)
+}
+
+int main() {
+  std::vector<int> indices;
+  std::vector<double> values;
+  indices.push_back(75);
+  values.push_back(1.028);
+  indices.push_back(74);
+  values.push_back(7.951);
+  Run(indices, values);
+}

diff  --git a/compiler-rt/test/nsan/swap.cpp b/compiler-rt/test/nsan/swap.cpp
new file mode 100644
index 00000000000000..0e1d9c8a880c02
--- /dev/null
+++ b/compiler-rt/test/nsan/swap.cpp
@@ -0,0 +1,46 @@
+// RUN: %clangxx_nsan -O2 %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_nsan -fno-builtin -O2 %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// This verifies that shadow memory is tracked correcty across typed and
+// bitcasted swaps.
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+extern "C" void __nsan_dump_shadow_mem(const char *addr, size_t size_bytes,
+                                       size_t bytes_per_line, size_t reserved);
+
+__attribute__((noinline)) void SwapFT(double &a, double &b) {
+  // LLVM typically optimizes this to an untyped swap (through i64) anyway.
+  std::swap(a, b);
+}
+
+__attribute__((noinline)) void SwapBitcasted(uint64_t &a, uint64_t &b) {
+  std::swap(a, b);
+}
+
+int main() {
+  double a = 1.0, b = 2.0;
+  __nsan_dump_shadow_mem((const char *)&a, sizeof(a), sizeof(a), 0);
+  __nsan_dump_shadow_mem((const char *)&b, sizeof(b), sizeof(b), 0);
+  SwapFT(a, b);
+  __nsan_dump_shadow_mem((const char *)&a, sizeof(a), sizeof(a), 0);
+  __nsan_dump_shadow_mem((const char *)&b, sizeof(b), sizeof(b), 0);
+  assert(a == 2.0 && b == 1.0);
+  SwapBitcasted(*reinterpret_cast<uint64_t *>(&a),
+                *reinterpret_cast<uint64_t *>(&b));
+  __nsan_dump_shadow_mem((const char *)&a, sizeof(a), sizeof(a), 0);
+  __nsan_dump_shadow_mem((const char *)&b, sizeof(b), sizeof(b), 0);
+  assert(a == 1.0 && b == 2.0);
+  // CHECK: 0x{{[a-f0-9]*}}:    d0 d1 d2 d3 d4 d5 d6 d7   (1.0{{.*}}
+  // CHECK-NEXT: 0x{{[a-f0-9]*}}:    d0 d1 d2 d3 d4 d5 d6 d7   (2.0{{.*}}
+  // CHECK-NEXT: 0x{{[a-f0-9]*}}:    d0 d1 d2 d3 d4 d5 d6 d7   (2.0{{.*}}
+  // CHECK-NEXT: 0x{{[a-f0-9]*}}:    d0 d1 d2 d3 d4 d5 d6 d7   (1.0{{.*}}
+  // CHECK-NEXT: 0x{{[a-f0-9]*}}:    d0 d1 d2 d3 d4 d5 d6 d7   (1.0{{.*}}
+  // CHECK-NEXT: 0x{{[a-f0-9]*}}:    d0 d1 d2 d3 d4 d5 d6 d7   (2.0{{.*}}
+}


        


More information about the llvm-commits mailing list