================
@@ -0,0 +1,134 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=alignment,null \
+// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-UBSAN
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK-NO-UBSAN
+
+// Test that EmitAggregateCopy emits null and alignment checks when sanitizers
+// are enabled for aggregate copy operations with pointers.
+
+struct alignas(16) AlignedStruct {
+ int a;
+ int b;
+ int c;
+ int d;
+};
+
+struct NormalStruct {
+ int x;
+ int y;
+ int z;
+};
+
+// Stack-to-stack copies are optimized away (compiler knows they're valid)
+// CHECK-UBSAN-LABEL: define {{.*}}void @_Z19test_aligned_structv()
+// CHECK-NO-UBSAN-LABEL: define {{.*}}void @_Z19test_aligned_structv()
+void test_aligned_struct() {
+ AlignedStruct src = {1, 2, 3, 4};
+ AlignedStruct dest;
+
+ // CHECK-UBSAN: call void @llvm.memcpy
+ // CHECK-NO-UBSAN: call void @llvm.memcpy
+
+ dest = src;
+}
+
+// CHECK-UBSAN-LABEL: define {{.*}}void @_Z18test_normal_structv()
+// CHECK-NO-UBSAN-LABEL: define {{.*}}void @_Z18test_normal_structv()
+void test_normal_struct() {
+ NormalStruct src = {10, 20, 30};
+ NormalStruct dest;
+
+ // CHECK-UBSAN: call void @llvm.memcpy
+ // CHECK-NO-UBSAN: call void @llvm.memcpy
+
+ dest = src;
+}
+
+// This is the key test - copying through pointers requires runtime checks
+// CHECK-UBSAN-LABEL: define {{.*}}void
@_Z19test_pointer_to_ptrP13AlignedStructS0_(
+// CHECK-NO-UBSAN-LABEL: define {{.*}}void
@_Z19test_pointer_to_ptrP13AlignedStructS0_(
+void test_pointer_to_ptr(AlignedStruct *src, AlignedStruct *dest) {
+ // CHECK-UBSAN: %[[SRC_LOAD:.*]] = load ptr, ptr %src.addr
+ // CHECK-UBSAN: %[[DEST_LOAD:.*]] = load ptr, ptr %dest.addr
+
+ // Check source pointer is non-null and aligned
+ // CHECK-UBSAN: %[[SRC_NONNULL:.*]] = icmp ne ptr %[[SRC_LOAD]], null
+ // CHECK-UBSAN: %[[SRC_INT:.*]] = ptrtoint ptr %[[SRC_LOAD]] to i64
+ // CHECK-UBSAN: %[[SRC_MASK:.*]] = and i64 %[[SRC_INT]], 15
+ // CHECK-UBSAN: %[[SRC_ALIGNED:.*]] = icmp eq i64 %[[SRC_MASK]], 0
+ // CHECK-UBSAN: %[[SRC_OK:.*]] = and i1 %[[SRC_NONNULL]], %[[SRC_ALIGNED]]
+ // CHECK-UBSAN: br i1 %[[SRC_OK]], label %cont, label %handler.type_mismatch
+
+ // CHECK-UBSAN: handler.type_mismatch:
+ // CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1_abort
+ // CHECK-UBSAN: unreachable
+
+ // CHECK-UBSAN: cont:
+ // Check destination pointer is non-null and aligned
+ // CHECK-UBSAN: %[[DEST_NONNULL:.*]] = icmp ne ptr %[[DEST_LOAD]], null
+ // CHECK-UBSAN: %[[DEST_INT:.*]] = ptrtoint ptr %[[DEST_LOAD]] to i64
+ // CHECK-UBSAN: %[[DEST_MASK:.*]] = and i64 %[[DEST_INT]], 15
+ // CHECK-UBSAN: %[[DEST_ALIGNED:.*]] = icmp eq i64 %[[DEST_MASK]], 0
+ // CHECK-UBSAN: %[[DEST_OK:.*]] = and i1 %[[DEST_NONNULL]], %[[DEST_ALIGNED]]
+ // CHECK-UBSAN: br i1 %[[DEST_OK]], label %cont{{.*}}, label
%handler.type_mismatch
+
+ // CHECK-UBSAN: handler.type_mismatch{{.*}}:
+ // CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1_abort
+ // CHECK-UBSAN: unreachable
+
+ // CHECK-UBSAN: cont{{.*}}:
+ // CHECK-UBSAN: call void @llvm.memcpy
+
+ // Without sanitizers, no checks - just direct memcpy
+ // CHECK-NO-UBSAN-NOT: @__ubsan_handle
+ // CHECK-NO-UBSAN: call void @llvm.memcpy
+
+ *dest = *src;
+}
+
+// Array copies also need checks for non-constant indices
----------------
vasu-the-sharma wrote:
I've modified `test_array_copy()` to accept an 'int idx' parameter and perform
a single array element copy using that non-constant index. This ensures the
compiler cannot optimize away the alignment checks and properly tests the
runtime sanitizer behavior for array element access with dynamic indices.
Changed from:
```
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
```
To:
```
void test_array_copy(int idx) {
...
dest[idx] = src[idx];
}
```
https://github.com/llvm/llvm-project/pull/164548
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits