access-softek / llvm-project

Other
0 stars 0 forks source link

[Pauth] Fix non-deterministic output in ptrauth-struct-attr clang tests #51

Open kovdan01 opened 11 months ago

kovdan01 commented 11 months ago

The following tests have non-deterministic output:

Before 545be4e49d8d92a2ed150c17568ba62fd76c7ef9, they failed on @kovdan01 's Linux machine and passed on @asl 's MacOS machine.

The test output on @kovdan01 's machine is correct, but it does not match the reference output due to rearranged IR instructions order. The output does not change when applying LLVM_REVERSE_ITERATION=1 on cmake build configuration phase.

See the output for unstable functions:

CodeGenCXX/ptrauth-struct-attr.cpp: ``` ; Function Attrs: mustprogress nounwind define void @_Z16test_assignment2P2S4S0_(ptr %a, ptr %b) #0 { entry: %a.addr = alloca ptr, align 8 %b.addr = alloca ptr, align 8 store ptr %a, ptr %a.addr, align 8, !tbaa !2 store ptr %b, ptr %b.addr, align 8, !tbaa !2 %0 = load ptr, ptr %b.addr, align 8, !tbaa !2 %1 = load ptr, ptr %a.addr, align 8, !tbaa !2 %2 = ptrtoint ptr %0 to i64 %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 1, i64 104) %4 = inttoptr i64 %3 to ptr %5 = ptrtoint ptr %1 to i64 %6 = call i64 @llvm.ptrauth.auth(i64 %5, i32 1, i64 104) %7 = inttoptr i64 %6 to ptr call void @llvm.memcpy.p0.p0.i64(ptr align 4 %7, ptr align 4 %4, i64 8, i1 false), !tbaa.struct !6 ret void } ``` CodeGenObjC/ptrauth-struct-attr.m: ``` ; Function Attrs: noinline nounwind optnone define void @test_dereference0(ptr %a0, ptr %a1) #0 { entry: %a0.addr = alloca ptr, align 8 %a1.addr = alloca ptr, align 8 store ptr %a0, ptr %a0.addr, align 8 store ptr %a1, ptr %a1.addr, align 8 %0 = load ptr, ptr %a0.addr, align 8 %1 = load ptr, ptr %a1.addr, align 8 %2 = ptrtoint ptr %1 to i64 %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 1, i64 100) %4 = inttoptr i64 %3 to ptr %5 = ptrtoint ptr %0 to i64 %6 = call i64 @llvm.ptrauth.auth(i64 %5, i32 1, i64 100) %7 = inttoptr i64 %6 to ptr call void @llvm.memcpy.p0.p0.i64(ptr align 4 %7, ptr align 4 %4, i64 8, i1 false) ret void } ```

The commit 545be4e49d8d92a2ed150c17568ba62fd76c7ef9 makes the tests accept both output variants, but it also allows some forms of incorrect IR to make the test pass.

asl commented 11 months ago

For the record, here is output on Mac host:

define void @_Z16test_assignment2P2S4S0_(ptr %a, ptr %b) #0 {
entry:
  %a.addr = alloca ptr, align 8
  %b.addr = alloca ptr, align 8
  store ptr %a, ptr %a.addr, align 8, !tbaa !2
  store ptr %b, ptr %b.addr, align 8, !tbaa !2
  %0 = load ptr, ptr %b.addr, align 8, !tbaa !2
  %1 = load ptr, ptr %a.addr, align 8, !tbaa !2
  %2 = ptrtoint ptr %1 to i64
  %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 1, i64 104)
  %4 = inttoptr i64 %3 to ptr
  %5 = ptrtoint ptr %0 to i64
  %6 = call i64 @llvm.ptrauth.auth(i64 %5, i32 1, i64 104)
  %7 = inttoptr i64 %6 to ptr
  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %4, ptr align 4 %7, i64 8, i1 false), !tbaa.struct !6
  ret void
}
asl commented 11 months ago

Tagging @ahmedbougacha

Here is CGBuilder::CreateMemCpy:

  using CGBuilderBaseTy::CreateMemCpy;
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
                               bool IsVolatile = false) {
    return CreateMemCpy(getRawPointerFromAddress(Dest),
                        Dest.getAlignment().getAsAlign(),
                        getRawPointerFromAddress(Src),
                        Src.getAlignment().getAsAlign(), Size, IsVolatile);
  }

Note that getRawPointerFromAddress has side effects. Since function argument evaluation order is unspecified, the side effects (llvm.ptrauth.auth calls) are happening in different order depending on the host.

The issue likely should be fixed as a part of https://github.com/llvm/llvm-project/pull/67454