[compiler-rt] [compiler-rt][nsan] Add more tests for shadow memory (PR #100906)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 27 16:08:22 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: Alexander Shaposhnikov (alexander-shaposhnikov)
<details>
<summary>Changes</summary>
Add more tests for shadow memory.
---
Full diff: https://github.com/llvm/llvm-project/pull/100906.diff
2 Files Affected:
- (added) compiler-rt/test/nsan/stable_sort.cpp (+55)
- (added) compiler-rt/test/nsan/swap.cpp (+46)
``````````diff
diff --git a/compiler-rt/test/nsan/stable_sort.cpp b/compiler-rt/test/nsan/stable_sort.cpp
new file mode 100644
index 0000000000000..db839d32121fd
--- /dev/null
+++ b/compiler-rt/test/nsan/stable_sort.cpp
@@ -0,0 +1,55 @@
+// RUN: %clangxx_nsan -O2 -g %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// 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 (int 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 0000000000000..c42c52356e625
--- /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{{.*}}
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/100906
More information about the llvm-commits
mailing list