| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,185 @@ | ||
| /*===---- ptrauth.h - Pointer authentication -------------------------------=== | ||
| * | ||
| * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| * See https://llvm.org/LICENSE.txt for license information. | ||
| * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| * | ||
| *===-----------------------------------------------------------------------=== | ||
| */ | ||
|
|
||
| #ifndef __PTRAUTH_H | ||
| #define __PTRAUTH_H | ||
|
|
||
| typedef enum { | ||
| ptrauth_key_asia = 0, | ||
| ptrauth_key_asib = 1, | ||
| ptrauth_key_asda = 2, | ||
| ptrauth_key_asdb = 3, | ||
| } ptrauth_key; | ||
|
|
||
| /* An integer type of the appropriate size for a discriminator argument. */ | ||
| typedef __UINTPTR_TYPE__ ptrauth_extra_data_t; | ||
|
|
||
| /* An integer type of the appropriate size for a generic signature. */ | ||
| typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; | ||
|
|
||
| /* A signed pointer value embeds the original pointer together with | ||
| a signature that attests to the validity of that pointer. Because | ||
| this signature must use only "spare" bits of the pointer, a | ||
| signature's validity is probabilistic in practice: it is unlikely | ||
| but still plausible that an invalidly-derived signature will | ||
| somehow equal the correct signature and therefore successfully | ||
| authenticate. Nonetheless, this scheme provides a strong degree | ||
| of protection against certain kinds of attacks. */ | ||
|
|
||
| /* Authenticating a pointer that was not signed with the given key | ||
| and extra-data value will (likely) fail by trapping. */ | ||
|
|
||
| #if __has_feature(ptrauth_intrinsics) | ||
|
|
||
| /* Strip the signature from a value without authenticating it. | ||
| If the value is a function pointer, the result will not be a | ||
| legal function pointer because of the missing signature, and | ||
| attempting to call it will result in an authentication failure. | ||
| The value must be an expression of pointer type. | ||
| The key must be a constant expression of type ptrauth_key. | ||
| The result will have the same type as the original value. */ | ||
| #define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key) | ||
|
|
||
| /* Blend a constant discriminator into the given pointer-like value | ||
| to form a new discriminator. Not all bits of the inputs are | ||
| guaranteed to contribute to the result. | ||
| On arm64e, the integer must fall within the range of a uint16_t; | ||
| other bits may be ignored. | ||
| The first argument must be an expression of pointer type. | ||
| The second argument must be an expression of integer type. | ||
| The result will have type uintptr_t. */ | ||
| #define ptrauth_blend_discriminator(__pointer, __integer) \ | ||
| __builtin_ptrauth_blend_discriminator(__pointer, __integer) | ||
|
|
||
| /* Add a signature to the given pointer value using a specific key, | ||
| using the given extra data as a salt to the signing process. | ||
| This operation does not authenticate the original value and is | ||
| therefore potentially insecure if an attacker could possibly | ||
| control that value. | ||
| The value must be an expression of pointer type. | ||
| The key must be a constant expression of type ptrauth_key. | ||
| The extra data must be an expression of pointer or integer type; | ||
| if an integer, it will be coerced to ptrauth_extra_data_t. | ||
| The result will have the same type as the original value. */ | ||
| #define ptrauth_sign_unauthenticated(__value, __key, __data) \ | ||
| __builtin_ptrauth_sign_unauthenticated(__value, __key, __data) | ||
|
|
||
| /* Authenticate a pointer using one scheme and resign it using another. | ||
| If the result is subsequently authenticated using the new scheme, that | ||
| authentication is guaranteed to fail if and only if the initial | ||
| authentication failed. | ||
| The value must be an expression of pointer type. | ||
| The key must be a constant expression of type ptrauth_key. | ||
| The extra data must be an expression of pointer or integer type; | ||
| if an integer, it will be coerced to ptrauth_extra_data_t. | ||
| The result will have the same type as the original value. | ||
| This operation is guaranteed to not leave the intermediate value | ||
| available for attack before it is re-signed. | ||
| Do not pass a null pointer to this function. A null pointer | ||
| will not successfully authenticate. | ||
| This operation traps if the authentication fails. */ | ||
| #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ | ||
| __new_data) \ | ||
| __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ | ||
| __new_data) | ||
|
|
||
| /* Authenticate a data pointer. | ||
| The value must be an expression of non-function pointer type. | ||
| The key must be a constant expression of type ptrauth_key. | ||
| The extra data must be an expression of pointer or integer type; | ||
| if an integer, it will be coerced to ptrauth_extra_data_t. | ||
| The result will have the same type as the original value. | ||
| This operation traps if the authentication fails. */ | ||
| #define ptrauth_auth_data(__value, __old_key, __old_data) \ | ||
| __builtin_ptrauth_auth(__value, __old_key, __old_data) | ||
|
|
||
| /* Compute a signature for the given pair of pointer-sized values. | ||
| The order of the arguments is significant. | ||
| Like a pointer signature, the resulting signature depends on | ||
| private key data and therefore should not be reliably reproducible | ||
| by attackers. That means that this can be used to validate the | ||
| integrity of arbitrary data by storing a signature for that data | ||
| alongside it, then checking that the signature is still valid later. | ||
| Data which exceeds two pointers in size can be signed by either | ||
| computing a tree of generic signatures or just signing an ordinary | ||
| cryptographic hash of the data. | ||
| The result has type ptrauth_generic_signature_t. However, it may | ||
| not have as many bits of entropy as that type's width would suggest; | ||
| some implementations are known to compute a compressed signature as | ||
| if the arguments were a pointer and a discriminator. | ||
| The arguments must be either pointers or integers; if integers, they | ||
| will be coerce to uintptr_t. */ | ||
| #define ptrauth_sign_generic_data(__value, __data) \ | ||
| __builtin_ptrauth_sign_generic_data(__value, __data) | ||
|
|
||
| #else | ||
|
|
||
| #define ptrauth_strip(__value, __key) \ | ||
| ({ \ | ||
| (void)__key; \ | ||
| __value; \ | ||
| }) | ||
|
|
||
| #define ptrauth_blend_discriminator(__pointer, __integer) \ | ||
| ({ \ | ||
| (void)__pointer; \ | ||
| (void)__integer; \ | ||
| ((ptrauth_extra_data_t)0); \ | ||
| }) | ||
|
|
||
| #define ptrauth_sign_unauthenticated(__value, __key, __data) \ | ||
| ({ \ | ||
| (void)__key; \ | ||
| (void)__data; \ | ||
| __value; \ | ||
| }) | ||
|
|
||
| #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ | ||
| __new_data) \ | ||
| ({ \ | ||
| (void)__old_key; \ | ||
| (void)__old_data; \ | ||
| (void)__new_key; \ | ||
| (void)__new_data; \ | ||
| __value; \ | ||
| }) | ||
|
|
||
| #define ptrauth_auth_data(__value, __old_key, __old_data) \ | ||
| ({ \ | ||
| (void)__old_key; \ | ||
| (void)__old_data; \ | ||
| __value; \ | ||
| }) | ||
|
|
||
| #define ptrauth_sign_generic_data(__value, __data) \ | ||
| ({ \ | ||
| (void)__value; \ | ||
| (void)__data; \ | ||
| ((ptrauth_generic_signature_t)0); \ | ||
| }) | ||
|
|
||
| #endif /* __has_feature(ptrauth_intrinsics) */ | ||
|
|
||
| #endif /* __PTRAUTH_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-intrinsics -emit-llvm %s -o - | FileCheck %s | ||
|
|
||
| void (*fnptr)(void); | ||
| long int_discriminator; | ||
| void *ptr_discriminator; | ||
| long signature; | ||
|
|
||
| // CHECK-LABEL: define void @test_auth() | ||
| void test_auth() { | ||
| // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, | ||
| // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, | ||
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 | ||
| // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 | ||
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 0, i64 [[DISC]]) | ||
| // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr | ||
| // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, | ||
| fnptr = __builtin_ptrauth_auth(fnptr, 0, ptr_discriminator); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define void @test_strip() | ||
| void test_strip() { | ||
| // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, | ||
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 | ||
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.strip(i64 [[T0]], i32 0) | ||
| // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr | ||
| // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, | ||
| fnptr = __builtin_ptrauth_strip(fnptr, 0); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define void @test_sign_unauthenticated() | ||
| void test_sign_unauthenticated() { | ||
| // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, | ||
| // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, | ||
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 | ||
| // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 | ||
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[T0]], i32 0, i64 [[DISC]]) | ||
| // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr | ||
| // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, | ||
| fnptr = __builtin_ptrauth_sign_unauthenticated(fnptr, 0, ptr_discriminator); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define void @test_auth_and_resign() | ||
| void test_auth_and_resign() { | ||
| // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, | ||
| // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, | ||
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 | ||
| // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 | ||
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 [[DISC]], i32 3, i64 15) | ||
| // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr | ||
| // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, | ||
| fnptr = __builtin_ptrauth_auth_and_resign(fnptr, 0, ptr_discriminator, 3, 15); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define void @test_blend_discriminator() | ||
| void test_blend_discriminator() { | ||
| // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, | ||
| // CHECK-NEXT: [[DISC:%.*]] = load i64, ptr @int_discriminator, | ||
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 | ||
| // CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 [[DISC]]) | ||
| // CHECK-NEXT: store i64 [[RESULT]], ptr @int_discriminator, | ||
| int_discriminator = __builtin_ptrauth_blend_discriminator(fnptr, int_discriminator); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define void @test_sign_generic_data() | ||
| void test_sign_generic_data() { | ||
| // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, | ||
| // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, | ||
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 | ||
| // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 | ||
| // CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.ptrauth.sign.generic(i64 [[T0]], i64 [[DISC]]) | ||
| // CHECK-NEXT: store i64 [[RESULT]], ptr @signature, | ||
| signature = __builtin_ptrauth_sign_generic_data(fnptr, ptr_discriminator); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,61 +1,35 @@ | ||
| /// Test -m[no-]unaligned-access and -m[no-]strict-align options. | ||
|
|
||
| // RUN: %clang --target=loongarch64 -mstrict-align -fsyntax-only %s -### 2>&1 | \ | ||
| // RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED | ||
| // RUN: %clang --target=loongarch64 -mno-strict-align -fsyntax-only %s -### 2>&1 | \ | ||
| // RUN: FileCheck %s --check-prefix=CC1-UNALIGNED | ||
| // RUN: %clang --target=loongarch64 -mstrict-align -mno-strict-align -fsyntax-only %s -### 2>&1 | \ | ||
| // RUN: FileCheck %s --check-prefix=CC1-UNALIGNED | ||
| // RUN: %clang --target=loongarch64 -mno-strict-align -mstrict-align -fsyntax-only %s -### 2>&1 | \ | ||
| // RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED | ||
|
|
||
| // RUN: %clang --target=loongarch64 -mstrict-align -S -emit-llvm %s -o - | \ | ||
| // RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED | ||
| // RUN: %clang --target=loongarch64 -mno-strict-align -S -emit-llvm %s -o - | \ | ||
| // RUN: FileCheck %s --check-prefix=IR-UNALIGNED | ||
| // RUN: %clang --target=loongarch64 -mstrict-align -mno-strict-align -S -emit-llvm %s -o - | \ | ||
| // RUN: FileCheck %s --check-prefix=IR-UNALIGNED | ||
| // RUN: %clang --target=loongarch64 -mno-strict-align -mstrict-align -S -emit-llvm %s -o - | \ | ||
| // RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED | ||
|
|
||
| // RUN: not %clang -### --target=loongarch64 -mno-unaligned-access -munaligned-access %s 2>&1 | \ | ||
| // RUN: FileCheck %s --check-prefix=ERR | ||
|
|
||
| // CC1-UNALIGNED: "-target-feature" "+ual" | ||
| // CC1-NO-UNALIGNED: "-target-feature" "-ual" | ||
|
|
||
| // IR-UNALIGNED: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+ual{{(,.*)?}}" | ||
| // IR-NO-UNALIGNED: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-ual{{(,.*)?}}" | ||
|
|
||
| // ERR: error: unsupported option '-mno-unaligned-access' for target 'loongarch64' | ||
| // ERR: error: unsupported option '-munaligned-access' for target 'loongarch64' | ||
|
|
||
| int foo(void) { | ||
| return 3; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,9 @@ | ||
| /// Check -m[no-]unaligned-access and -m[no-]strict-align are errored on a target that does not support them. | ||
|
|
||
| // RUN: not %clang --target=x86_64 -munaligned-access -fsyntax-only %s -### 2>&1 | FileCheck %s -DOPTION=unaligned-access | ||
| // RUN: not %clang --target=x86_64 -mno-unaligned-access -fsyntax-only %s -### 2>&1 | FileCheck %s -DOPTION=no-unaligned-access | ||
| // RUN: not %clang --target=x86_64 -mno-strict-align -mstrict-align -fsyntax-only %s -### 2>&1 | FileCheck %s --check-prefix=ALIGN | ||
|
|
||
| // CHECK: error: unsupported option '-m{{(no-)?}}unaligned-access' for target '{{.*}}' | ||
| // ALIGN: error: unsupported option '-mno-strict-align' for target '{{.*}}' | ||
| // ALIGN: error: unsupported option '-mstrict-align' for target '{{.*}}' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,7 +61,7 @@ int r; | |
| #ifdef __BPF_FEATURE_ST | ||
| int s; | ||
| #endif | ||
| #ifdef __BPF_FEATURE_ADDR_SPACE_CAST | ||
| int t; | ||
| #endif | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // RUN: %clang_cc1 %s -E -triple=arm64-- | FileCheck %s --check-prefixes=NOINTRIN | ||
| // RUN: %clang_cc1 %s -E -triple=arm64-- -fptrauth-intrinsics | FileCheck %s --check-prefixes=INTRIN | ||
|
|
||
| #if __has_feature(ptrauth_intrinsics) | ||
| // INTRIN: has_ptrauth_intrinsics | ||
| void has_ptrauth_intrinsics() {} | ||
| #else | ||
| // NOINTRIN: no_ptrauth_intrinsics | ||
| void no_ptrauth_intrinsics() {} | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // RUN: %clang_cc1 -triple arm64-apple-ios -Wall -fsyntax-only -verify -fptrauth-intrinsics %s | ||
| // RUN: %clang_cc1 -triple arm64-apple-ios -Wall -fsyntax-only -verify %s | ||
|
|
||
| // expected-no-diagnostics | ||
|
|
||
| #include <ptrauth.h> | ||
|
|
||
| #define VALID_CODE_KEY 0 | ||
| #define VALID_DATA_KEY 2 | ||
|
|
||
| extern int dv; | ||
|
|
||
| void test(int *dp, int value) { | ||
| dp = ptrauth_strip(dp, VALID_DATA_KEY); | ||
| ptrauth_extra_data_t t0 = ptrauth_blend_discriminator(dp, value); | ||
| (void)t0; | ||
| dp = ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, 0); | ||
| dp = ptrauth_auth_and_resign(dp, VALID_DATA_KEY, dp, VALID_DATA_KEY, dp); | ||
| dp = ptrauth_auth_data(dp, VALID_DATA_KEY, 0); | ||
| int pu0 = 0, pu1 = 0, pu2 = 0, pu3 = 0, pu4 = 0, pu5 = 0, pu6 = 0, pu7 = 0; | ||
| ptrauth_blend_discriminator(&pu0, value); | ||
| ptrauth_auth_and_resign(&pu1, VALID_DATA_KEY, dp, VALID_DATA_KEY, dp); | ||
| ptrauth_auth_and_resign(dp, VALID_DATA_KEY, &pu2, VALID_DATA_KEY, dp); | ||
| ptrauth_auth_and_resign(dp, VALID_DATA_KEY, dp, VALID_DATA_KEY, &pu3); | ||
| ptrauth_sign_generic_data(pu4, dp); | ||
| ptrauth_sign_generic_data(dp, pu5); | ||
| ptrauth_auth_data(&pu6, VALID_DATA_KEY, value); | ||
| ptrauth_auth_data(dp, VALID_DATA_KEY, pu7); | ||
|
|
||
|
|
||
|
|
||
| int t2 = ptrauth_sign_generic_data(dp, 0); | ||
| (void)t2; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| // RUN: %clang_cc1 -triple arm64-apple-ios -fsyntax-only -verify -fptrauth-intrinsics %s | ||
|
|
||
| #if __has_feature(ptrauth_intrinsics) | ||
| #warning Pointer authentication enabled! | ||
| // expected-warning@-1 {{Pointer authentication enabled!}} | ||
| #endif | ||
|
|
||
| #if __aarch64__ | ||
| #define VALID_CODE_KEY 0 | ||
| #define VALID_DATA_KEY 2 | ||
| #define INVALID_KEY 200 | ||
| #else | ||
| #error Provide these constants if you port this test | ||
| #endif | ||
|
|
||
| #define NULL ((void*) 0) | ||
| struct A { int x; } mismatched_type; | ||
|
|
||
| extern int dv; | ||
| extern int fv(int); | ||
|
|
||
| void test_strip(int *dp, int (*fp)(int)) { | ||
| __builtin_ptrauth_strip(dp); // expected-error {{too few arguments}} | ||
| __builtin_ptrauth_strip(dp, VALID_DATA_KEY, dp); // expected-error {{too many arguments}} | ||
| (void) __builtin_ptrauth_strip(NULL, VALID_DATA_KEY); // no warning | ||
|
|
||
| __builtin_ptrauth_strip(mismatched_type, VALID_DATA_KEY); // expected-error {{signed value must have pointer type; type here is 'struct A'}} | ||
| __builtin_ptrauth_strip(dp, mismatched_type); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} | ||
|
|
||
| int *dr = __builtin_ptrauth_strip(dp, VALID_DATA_KEY); | ||
| dr = __builtin_ptrauth_strip(dp, INVALID_KEY); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| int (*fr)(int) = __builtin_ptrauth_strip(fp, VALID_CODE_KEY); | ||
| fr = __builtin_ptrauth_strip(fp, INVALID_KEY); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| float *mismatch = __builtin_ptrauth_strip(dp, VALID_DATA_KEY); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} | ||
| } | ||
|
|
||
| void test_blend_discriminator(int *dp, int (*fp)(int), int value) { | ||
| __builtin_ptrauth_blend_discriminator(dp); // expected-error {{too few arguments}} | ||
| __builtin_ptrauth_blend_discriminator(dp, dp, dp); // expected-error {{too many arguments}} | ||
| (void) __builtin_ptrauth_blend_discriminator(dp, value); // no warning | ||
|
|
||
| __builtin_ptrauth_blend_discriminator(mismatched_type, value); // expected-error {{blended pointer must have pointer type; type here is 'struct A'}} | ||
| __builtin_ptrauth_blend_discriminator(dp, mismatched_type); // expected-error {{blended integer must have integer type; type here is 'struct A'}} | ||
|
|
||
| float *mismatch = __builtin_ptrauth_blend_discriminator(dp, value); // expected-error {{incompatible integer to pointer conversion initializing 'float *' with an expression of type}} | ||
| } | ||
|
|
||
| void test_sign_unauthenticated(int *dp, int (*fp)(int)) { | ||
| __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY); // expected-error {{too few arguments}} | ||
| __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, dp, dp); // expected-error {{too many arguments}} | ||
|
|
||
| __builtin_ptrauth_sign_unauthenticated(mismatched_type, VALID_DATA_KEY, 0); // expected-error {{signed value must have pointer type; type here is 'struct A'}} | ||
| __builtin_ptrauth_sign_unauthenticated(dp, mismatched_type, 0); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} | ||
| __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} | ||
|
|
||
| (void) __builtin_ptrauth_sign_unauthenticated(NULL, VALID_DATA_KEY, 0); // expected-warning {{signing a null pointer will yield a non-null pointer}} | ||
|
|
||
| int *dr = __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, 0); | ||
| dr = __builtin_ptrauth_sign_unauthenticated(dp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| int (*fr)(int) = __builtin_ptrauth_sign_unauthenticated(fp, VALID_CODE_KEY, 0); | ||
| fr = __builtin_ptrauth_sign_unauthenticated(fp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| float *mismatch = __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, 0); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} | ||
| } | ||
|
|
||
| void test_auth(int *dp, int (*fp)(int)) { | ||
| __builtin_ptrauth_auth(dp, VALID_DATA_KEY); // expected-error {{too few arguments}} | ||
| __builtin_ptrauth_auth(dp, VALID_DATA_KEY, dp, dp); // expected-error {{too many arguments}} | ||
|
|
||
| __builtin_ptrauth_auth(mismatched_type, VALID_DATA_KEY, 0); // expected-error {{signed value must have pointer type; type here is 'struct A'}} | ||
| __builtin_ptrauth_auth(dp, mismatched_type, 0); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} | ||
| __builtin_ptrauth_auth(dp, VALID_DATA_KEY, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} | ||
|
|
||
| (void) __builtin_ptrauth_auth(NULL, VALID_DATA_KEY, 0); // expected-warning {{authenticating a null pointer will almost certainly trap}} | ||
|
|
||
| int *dr = __builtin_ptrauth_auth(dp, VALID_DATA_KEY, 0); | ||
| dr = __builtin_ptrauth_auth(dp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| int (*fr)(int) = __builtin_ptrauth_auth(fp, VALID_CODE_KEY, 0); | ||
| fr = __builtin_ptrauth_auth(fp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| float *mismatch = __builtin_ptrauth_auth(dp, VALID_DATA_KEY, 0); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} | ||
| } | ||
|
|
||
| void test_auth_and_resign(int *dp, int (*fp)(int)) { | ||
| __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY); // expected-error {{too few arguments}} | ||
| __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, dp, VALID_DATA_KEY, dp, 0); // expected-error {{too many arguments}} | ||
|
|
||
| __builtin_ptrauth_auth_and_resign(mismatched_type, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); // expected-error {{signed value must have pointer type; type here is 'struct A'}} | ||
| __builtin_ptrauth_auth_and_resign(dp, mismatched_type, 0, VALID_DATA_KEY, dp); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} | ||
| __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, mismatched_type, VALID_DATA_KEY, dp); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} | ||
| __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, mismatched_type, dp); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} | ||
| __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} | ||
|
|
||
| (void) __builtin_ptrauth_auth_and_resign(NULL, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); // expected-warning {{authenticating a null pointer will almost certainly trap}} | ||
|
|
||
| int *dr = __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); | ||
| dr = __builtin_ptrauth_auth_and_resign(dp, INVALID_KEY, 0, VALID_DATA_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
| dr = __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, INVALID_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| int (*fr)(int) = __builtin_ptrauth_auth_and_resign(fp, VALID_CODE_KEY, 0, VALID_CODE_KEY, dp); | ||
| fr = __builtin_ptrauth_auth_and_resign(fp, INVALID_KEY, 0, VALID_CODE_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
| fr = __builtin_ptrauth_auth_and_resign(fp, VALID_CODE_KEY, 0, INVALID_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} | ||
|
|
||
| float *mismatch = __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} | ||
| } | ||
|
|
||
| void test_sign_generic_data(int *dp) { | ||
| __builtin_ptrauth_sign_generic_data(dp); // expected-error {{too few arguments}} | ||
| __builtin_ptrauth_sign_generic_data(dp, 0, 0); // expected-error {{too many arguments}} | ||
|
|
||
| __builtin_ptrauth_sign_generic_data(mismatched_type, 0); // expected-error {{signed value must have pointer or integer type; type here is 'struct A'}} | ||
| __builtin_ptrauth_sign_generic_data(dp, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} | ||
|
|
||
| (void) __builtin_ptrauth_sign_generic_data(NULL, 0); // no warning | ||
|
|
||
| unsigned long dr = __builtin_ptrauth_sign_generic_data(dp, 0); | ||
| dr = __builtin_ptrauth_sign_generic_data(dp, &dv); | ||
| dr = __builtin_ptrauth_sign_generic_data(12314, 0); | ||
| dr = __builtin_ptrauth_sign_generic_data(12314, &dv); | ||
|
|
||
| int *mismatch = __builtin_ptrauth_sign_generic_data(dp, 0); // expected-error {{incompatible integer to pointer conversion initializing 'int *' with an expression of type}} | ||
| } |