Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
kovdan01 opened this issue Nov 14, 2023 · 2 comments
Open
Assignees
Labels

Comments

@kovdan01
Copy link
Contributor

The following tests have non-deterministic output:

  • Clang :: CodeGenCXX/ptrauth-struct-attr.cpp
  • Clang :: CodeGenObjC/ptrauth-struct-attr.m

Before 545be4e, 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 545be4e makes the tests accept both output variants, but it also allows some forms of incorrect IR to make the test pass.

@asl
Copy link
Contributor

asl commented Nov 21, 2023

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
Copy link
Contributor

asl commented Nov 21, 2023

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 llvm/llvm-project#67454

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants