[llvm-branch-commits] [compiler-rt] [TySan] Fix struct access with different bases (PR #108385)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Sep 12 06:24:44 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: None (gbMattN)

<details>
<summary>Changes</summary>

Fixes issue #<!-- -->105960

If a member in a struct is also a struct, accessing a member partway through this inner struct currently causes a false positive. This is because when checking aliasing, the access offset is seen as greater than the starting offset of the inner struct, so the loop continues one iteration, and believes we are accessing the member after the inner struct. 

The next member's offset is greater than the offset we are looking for, so when we subtract the next member's offset from what we are looking for, the offset underflows.

To fix this, we check if the member we think we are accessing has a greater offset than the offset we are looking for. If so, we take a step back. We cannot do this in the loop, since the loop does not check the final member. This means the penultimate member would still cause false positives.

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


2 Files Affected:

- (modified) compiler-rt/lib/tysan/tysan.cpp (+4) 
- (added) compiler-rt/test/tysan/struct-offset-different-base.cpp (+31) 


``````````diff
diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index f627851d049e6a..f2cb6faddf45ac 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -128,6 +128,10 @@ static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
           break;
       }
 
+      //You can't have negative offset, you must be partially inside the last type
+      if (TDA->Struct.Members[Idx].Offset > OffsetA)
+        Idx -=1;
+        
       OffsetA -= TDA->Struct.Members[Idx].Offset;
       TDA = TDA->Struct.Members[Idx].Type;
     } else {
diff --git a/compiler-rt/test/tysan/struct-offset-different-base.cpp b/compiler-rt/test/tysan/struct-offset-different-base.cpp
new file mode 100644
index 00000000000000..c1ef5f8669c280
--- /dev/null
+++ b/compiler-rt/test/tysan/struct-offset-different-base.cpp
@@ -0,0 +1,31 @@
+// RUN: %clangxx_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+
+struct inner {
+	char buffer;
+	int i;
+};
+
+void init_inner(inner *list) {
+	list->i = 0;
+}
+
+struct outer {
+	inner foo;
+    char buffer;
+};
+
+int main(void) {
+	outer *l = new outer();
+
+    init_inner(&l->foo);
+    
+    int access_offsets_with_different_base = l->foo.i;
+	printf("%d\n", access_offsets_with_different_base);
+    
+	return 0;
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation

``````````

</details>


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


More information about the llvm-branch-commits mailing list