[llvm-branch-commits] [compiler-rt] [TySan] Fixed false positive when accessing offset member variables (PR #95387)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Jun 13 03:46:39 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: None (gbMattN)

<details>
<summary>Changes</summary>

This patch fixes a bug the current TySan implementation has. Currently if you access a member variable other than the first, TySan reports an error. TySan believes you are accessing the struct type with an offset equal to the offset of the member variable you are trying to access.
With this patch, the type we are trying to access is amended to the type of the member variable matching the offset we are accessing with. It does this if and only if there is a member at that offset, however, so any incorrect accesses are still caught. This is checked in the struct-members.c test.

---
Full diff: https://github.com/llvm/llvm-project/pull/95387.diff


2 Files Affected:

- (modified) compiler-rt/lib/tysan/tysan.cpp (+11-1) 
- (added) compiler-rt/test/tysan/struct-members.c (+32) 


``````````diff
diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index f627851d049e6..747727e48a152 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -221,7 +221,17 @@ __tysan_check(void *addr, int size, tysan_type_descriptor *td, int flags) {
     OldTDPtr -= i;
     OldTD = *OldTDPtr;
 
-    if (!isAliasingLegal(td, OldTD))
+    tysan_type_descriptor *InternalMember = OldTD;
+    if (OldTD->Tag == TYSAN_STRUCT_TD) {
+      for (int j = 0; j < OldTD->Struct.MemberCount; j++) {
+        if (OldTD->Struct.Members[j].Offset == i) {
+          InternalMember = OldTD->Struct.Members[j].Type;
+          break;
+        }
+      }
+    }
+
+    if (!isAliasingLegal(td, InternalMember))
       reportError(addr, size, td, OldTD, AccessStr,
                   "accesses part of an existing object", -i, pc, bp, sp);
 
diff --git a/compiler-rt/test/tysan/struct-members.c b/compiler-rt/test/tysan/struct-members.c
new file mode 100644
index 0000000000000..8cf6499f78ce6
--- /dev/null
+++ b/compiler-rt/test/tysan/struct-members.c
@@ -0,0 +1,32 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+
+struct X {
+  int a, b, c;
+} x;
+
+static struct X xArray[2];
+
+int main() {
+  x.a = 1;
+  x.b = 2;
+  x.c = 3;
+
+  printf("%d %d %d\n", x.a, x.b, x.c);
+  // CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
+  for (size_t i = 0; i < 2; i++) {
+    xArray[i].a = 1;
+    xArray[i].b = 1;
+    xArray[i].c = 1;
+  }
+  printf("Here\n");
+
+  struct X *xPtr = (struct X *)&(xArray[0].c);
+  xPtr->a = 1;
+  // CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+  // CHECK: WRITE of size 4 at {{.*}} with type int (in X at offset 0) accesses an existing object of type int (in X at offset 8)
+  // CHECK: {{#0 0x.* in main .*struct-members.c:}}[[@LINE-3]]
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/95387


More information about the llvm-branch-commits mailing list