llvm-project/clang/test/CodeGenCXX/cfi-vcall-trap-recover-runtime.cpp
Vitaly Buka 73ddbd3c09
[NFC][CFI] Add tests for different reporting settings (#137225)
1. Trap
2. Abort from runtime
3. Recover from runtime
4. Abort from minimal runtime
5. Recover from minimal runtime

They already work as expected.
2025-04-24 12:29:26 -07:00

133 lines
8.6 KiB
C++

// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// RUN: %clang_cc1 -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=TRAP %s
// RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=ABORT %s
// RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -fsanitize-recover=cfi-vcall -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=RECOVER %s
// RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -fsanitize-minimal-runtime -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=ABORT_MIN %s
// RUN: %clang_cc1 -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -fsanitize-recover=cfi-vcall -fsanitize-minimal-runtime -flto -fvisibility=hidden -triple x86_64-unknown-linux -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=RECOVER_MIN %s
struct S1 {
virtual void f();
};
// TRAP-LABEL: define hidden void @_Z3s1fP2S1(
// TRAP-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
// TRAP-NEXT: [[ENTRY:.*:]]
// TRAP-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8
// TRAP-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8
// TRAP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8
// TRAP-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8
// TRAP-NEXT: [[TMP1:%.*]] = call { ptr, i1 } @llvm.type.checked.load(ptr [[VTABLE]], i32 0, metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]]
// TRAP-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i1 } [[TMP1]], 1, !nosanitize [[META5]]
// TRAP-NEXT: br i1 [[TMP2]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]]
// TRAP: [[TRAP]]:
// TRAP-NEXT: call void @llvm.ubsantrap(i8 2) #[[ATTR3:[0-9]+]], !nosanitize [[META5]]
// TRAP-NEXT: unreachable, !nosanitize [[META5]]
// TRAP: [[CONT]]:
// TRAP-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i1 } [[TMP1]], 0, !nosanitize [[META5]]
// TRAP-NEXT: call void [[TMP3]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]])
// TRAP-NEXT: ret void
//
// ABORT-LABEL: define hidden void @_Z3s1fP2S1(
// ABORT-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
// ABORT-NEXT: [[ENTRY:.*:]]
// ABORT-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8
// ABORT-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8
// ABORT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8
// ABORT-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8
// ABORT-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]]
// ABORT-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]]
// ABORT-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]]
// ABORT: [[HANDLER_CFI_CHECK_FAIL]]:
// ABORT-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64, !nosanitize [[META5]]
// ABORT-NEXT: [[TMP4:%.*]] = zext i1 [[TMP2]] to i64, !nosanitize [[META5]]
// ABORT-NEXT: call void @__ubsan_handle_cfi_check_fail_abort(ptr @anon.00e38160576ab76122d2f8d139d2e390.1, i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR3:[0-9]+]], !nosanitize [[META5]]
// ABORT-NEXT: unreachable, !nosanitize [[META5]]
// ABORT: [[CONT]]:
// ABORT-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0
// ABORT-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VFN]], align 8
// ABORT-NEXT: call void [[TMP5]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]])
// ABORT-NEXT: ret void
//
// RECOVER-LABEL: define hidden void @_Z3s1fP2S1(
// RECOVER-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
// RECOVER-NEXT: [[ENTRY:.*:]]
// RECOVER-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8
// RECOVER-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8
// RECOVER-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8
// RECOVER-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8
// RECOVER-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]]
// RECOVER-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]]
// RECOVER-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]]
// RECOVER: [[HANDLER_CFI_CHECK_FAIL]]:
// RECOVER-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64, !nosanitize [[META5]]
// RECOVER-NEXT: [[TMP4:%.*]] = zext i1 [[TMP2]] to i64, !nosanitize [[META5]]
// RECOVER-NEXT: call void @__ubsan_handle_cfi_check_fail(ptr @anon.00e38160576ab76122d2f8d139d2e390.1, i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR3:[0-9]+]], !nosanitize [[META5]]
// RECOVER-NEXT: br label %[[CONT]], !nosanitize [[META5]]
// RECOVER: [[CONT]]:
// RECOVER-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0
// RECOVER-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VFN]], align 8
// RECOVER-NEXT: call void [[TMP5]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]])
// RECOVER-NEXT: ret void
//
// ABORT_MIN-LABEL: define hidden void @_Z3s1fP2S1(
// ABORT_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
// ABORT_MIN-NEXT: [[ENTRY:.*:]]
// ABORT_MIN-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8
// ABORT_MIN-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8
// ABORT_MIN-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8
// ABORT_MIN-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8
// ABORT_MIN-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]]
// ABORT_MIN-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]]
// ABORT_MIN-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]]
// ABORT_MIN: [[HANDLER_CFI_CHECK_FAIL]]:
// ABORT_MIN-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal_abort() #[[ATTR3:[0-9]+]], !nosanitize [[META5]]
// ABORT_MIN-NEXT: unreachable, !nosanitize [[META5]]
// ABORT_MIN: [[CONT]]:
// ABORT_MIN-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0
// ABORT_MIN-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VFN]], align 8
// ABORT_MIN-NEXT: call void [[TMP3]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]])
// ABORT_MIN-NEXT: ret void
//
// RECOVER_MIN-LABEL: define hidden void @_Z3s1fP2S1(
// RECOVER_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
// RECOVER_MIN-NEXT: [[ENTRY:.*:]]
// RECOVER_MIN-NEXT: [[S1_ADDR:%.*]] = alloca ptr, align 8
// RECOVER_MIN-NEXT: store ptr [[S1]], ptr [[S1_ADDR]], align 8
// RECOVER_MIN-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S1_ADDR]], align 8
// RECOVER_MIN-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8
// RECOVER_MIN-NEXT: [[TMP1:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTS2S1"), !nosanitize [[META5:![0-9]+]]
// RECOVER_MIN-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"all-vtables"), !nosanitize [[META5]]
// RECOVER_MIN-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_CFI_CHECK_FAIL:.*]], !prof [[PROF6:![0-9]+]], !nosanitize [[META5]]
// RECOVER_MIN: [[HANDLER_CFI_CHECK_FAIL]]:
// RECOVER_MIN-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal() #[[ATTR3:[0-9]+]], !nosanitize [[META5]]
// RECOVER_MIN-NEXT: br label %[[CONT]], !nosanitize [[META5]]
// RECOVER_MIN: [[CONT]]:
// RECOVER_MIN-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0
// RECOVER_MIN-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VFN]], align 8
// RECOVER_MIN-NEXT: call void [[TMP3]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]])
// RECOVER_MIN-NEXT: ret void
//
void s1f(S1 *s1) {
s1->f();
}
//.
// TRAP: [[META5]] = !{}
// TRAP: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1}
//.
// ABORT: [[META5]] = !{}
// ABORT: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1}
//.
// RECOVER: [[META5]] = !{}
// RECOVER: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1}
//.
// ABORT_MIN: [[META5]] = !{}
// ABORT_MIN: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1}
//.
// RECOVER_MIN: [[META5]] = !{}
// RECOVER_MIN: [[PROF6]] = !{!"branch_weights", i32 1048575, i32 1}
//.