vasu-the-sharma wrote:
Hi @tonykuttai @hubert-reinterpretcast I've been working on the changes and
wanted to share the IR comparison to make sure we're on the right track.
### Code Changes
**clang/lib/CodeGen/CGExprAgg.cpp** (2 changes):
```
// Line ~249: RHS check in EmitAggLoadOfLValue
- LValue LV = CGF.EmitLValue(E);
+ LValue LV = CGF.EmitCheckedLValue(E, CodeGenFunction::TCK_Load);
// Line ~1340: LHS check in VisitBinAssign
- LValue LHS = CGF.EmitLValue(E->getLHS());
+ LValue LHS = CGF.EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
```
**clang/lib/CodeGen/CGClass.cpp** (1 change):
```cpp
- LValue Src = EmitLValue(Arg);
+ LValue Src = EmitCheckedLValue(Arg, TCK_Load);
```
**clang/lib/CodeGen/CGExprCXX.cpp** (1 change):
```cpp
- TrivialAssignmentRHS = EmitLValue(CE->getArg(1));
+ TrivialAssignmentRHS = EmitCheckedLValue(CE->getArg(1), TCK_Load);
```
### IR Comparison
I tested with this simple case:
```c
struct Agg { int x; };
void test_lhs(struct Agg *dest) {
struct Agg local = {0};
*dest = local;
}
```
**WITHOUT change** (no null/alignment check on dest):
```llvm
define dso_local void @test_lhs(ptr noundef %dest) #0 {
entry:
%dest.addr = alloca ptr, align 8
%local = alloca %struct.Agg, align 4
store ptr %dest, ptr %dest.addr, align 8
call void @llvm.memset.p0.i64(ptr align 4 %local, i8 0, i64 4, i1 false)
%0 = load ptr, ptr %dest.addr, align 8
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %0, ptr align 4 %local, i64 4,
i1 false)
ret void
}
```
**WITH change** (null + alignment check on dest before memcpy):
```llvm
define dso_local void @test_lhs(ptr noundef %dest) #0 {
entry:
%dest.addr = alloca ptr, align 8
%local = alloca %struct.Agg, align 4
store ptr %dest, ptr %dest.addr, align 8
call void @llvm.memset.p0.i64(ptr align 4 %local, i8 0, i64 4, i1 false)
%0 = load ptr, ptr %dest.addr, align 8
%1 = icmp ne ptr %0, null, !nosanitize !1
%2 = ptrtoint ptr %0 to i64, !nosanitize !1
%3 = and i64 %2, 3, !nosanitize !1
%4 = icmp eq i64 %3, 0, !nosanitize !1
%5 = and i1 %1, %4, !nosanitize !1
br i1 %5, label %cont, label %handler.type_mismatch, !prof !2, !nosanitize !1
handler.type_mismatch:
call void @__ubsan_handle_type_mismatch_v1_abort(ptr @1, i64 %2) #4,
!nosanitize !1
unreachable, !nosanitize !1
cont:
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %0, ptr align 4 %local, i64 4,
i1 false)
ret void
}
```
**UBSan call count (for test_lhs + test_rhs + test_both):**
- Without change: 3 (RHS checks only)
- With change: 5 (LHS + RHS checks)
### Proposed FileCheck Patterns
Based on the IR, I propose using `CHECK-NEXT:` for precise sequential matching:
```
// CHECK-LABEL: define {{.*}}@test_lhs(
// CHECK: [[DEST:%.*]] = load ptr, ptr %dest.addr
// CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[DEST]], null, !nosanitize
// CHECK-NEXT: [[INT:%.*]] = ptrtoint ptr [[DEST]] to i64, !nosanitize
// CHECK-NEXT: [[AND:%.*]] = and i64 [[INT]], 3, !nosanitize
// CHECK-NEXT: [[ALIGN:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize
// CHECK-NEXT: [[OK:%.*]] = and i1 [[CMP]], [[ALIGN]], !nosanitize
// CHECK-NEXT: br i1 [[OK]], label %cont, label %handler.type_mismatch
// CHECK: call void @__ubsan_handle_type_mismatch_v1_abort
// CHECK: call void @llvm.memcpy
```
@tonykuttai @hubert-reinterpretcast Does this look correct? Please let me know
if the patterns need adjustment or if additional test cases are needed. Thanks.
https://github.com/llvm/llvm-project/pull/190739
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits