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

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.

>From 2dffe46bc8af4ccd5627478ba9546647907104cc Mon Sep 17 00:00:00 2001
From: Matthew Nagy <gbm...@tiger-linux2.domain.snsys.com>
Date: Thu, 12 Sep 2024 12:36:57 +0000
Subject: [PATCH] [TySan] Fix struct access with different bases

---
 compiler-rt/lib/tysan/tysan.cpp               |  4 +++
 .../tysan/struct-offset-different-base.cpp    | 31 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 compiler-rt/test/tysan/struct-offset-different-base.cpp

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

_______________________________________________
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to