diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 76976012e8be6..613b312bf73a4 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -499,15 +499,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span), - ExprKind::DirectConstArg(_) => { - let e = self - .tcx - .dcx() - .struct_span_err( - e.span, - "expected expression, found `direct_const_arg!()` constant", - ) - .emit(); + ExprKind::DirectConstArg(expr) => { + let e = self.emit_bad_direct_const_arg(e.span, expr, "expression"); hir::ExprKind::Err(e) } }; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ffe24c2adfc95..c6cd3fe5f5922 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -53,7 +53,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_data_structures::unord::ExtendUnord; use rustc_errors::codes::*; -use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle}; +use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; @@ -1760,12 +1760,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let fields = self.arena.alloc_slice(fields); hir::TyKind::View(ty, fields) } - TyKind::DirectConstArg(_) => { - let e = self - .tcx - .dcx() - .struct_span_err(t.span, "expected type, found `direct_const_arg!()` constant") - .emit(); + TyKind::DirectConstArg(expr) => { + let e = self.emit_bad_direct_const_arg(t.span, expr, "type"); hir::TyKind::Err(e) } TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"), @@ -1774,6 +1770,22 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } } + pub(crate) fn emit_bad_direct_const_arg( + &mut self, + span: Span, + expr: &Expr, + expected: &'static str, + ) -> ErrorGuaranteed { + let msg = format!("expected {expected}, found `direct_const_arg!()` constant"); + if expr::WillCreateDefIdsVisitor.visit_expr(expr).is_break() { + // FIXME(mgca): make this non-fatal once we have a better way to handle + // nested items in invalid `direct_const_arg!()` arguments. + self.dcx().struct_span_fatal(span, msg).emit() + } else { + self.dcx().struct_span_err(span, msg).emit() + } + } + fn lower_ty_direct_lifetime( &mut self, t: &Ty, diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 7450f11f3ce80..e73b8aab54d73 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -2,12 +2,12 @@ use gccjit::{LValue, RValue, ToRValue, Type}; use rustc_abi::Primitive::Pointer; use rustc_abi::{self as abi, HasDataLayout}; use rustc_codegen_ssa::traits::{ - BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, PacMetadata, - StaticCodegenMethods, + BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods, }; use rustc_middle::mir::Mutability; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::layout::LayoutOf; +use rustc_session::PointerAuthSchema; use crate::consts::const_alloc_to_gcc; use crate::context::{CodegenCx, new_array_type}; @@ -247,7 +247,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>, - _pac: Option, + _schema: Option<&PointerAuthSchema>, ) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 3a6c415b38963..0e3fa72fbcfb3 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -5,9 +5,7 @@ use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RV use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; -use rustc_codegen_ssa::traits::{ - BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods, PacMetadata, -}; +use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::interpret::Allocation; @@ -18,9 +16,9 @@ use rustc_middle::ty::layout::{ LayoutOfHelpers, }; use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; -use rustc_session::Session; #[cfg(feature = "master")] use rustc_session::config::DebugInfo; +use rustc_session::{PointerAuthSchema, Session}; use rustc_span::{DUMMY_SP, Span, Symbol, respan}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; @@ -400,7 +398,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { get_fn(self, instance) } - fn get_fn_addr(&self, instance: Instance<'tcx>, _pac: Option) -> RValue<'gcc> { + fn get_fn_addr( + &self, + instance: Instance<'tcx>, + _pointer_auth_schema: Option<&PointerAuthSchema>, + ) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; let func = if let Some(variable) = self.get_declared_value(func_name) { diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 774ffa8df9342..1f00e47a89927 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,12 +12,9 @@ use rustc_session::config::{ }; use rustc_span::sym; use rustc_symbol_mangling::mangle_internal_symbol; -use rustc_target::spec::{ - Arch, FramePointer, LlvmAbi, SanitizerSet, StackProbeType, StackProtector, -}; +use rustc_target::spec::{Arch, FramePointer, SanitizerSet, StackProbeType, StackProtector}; use smallvec::SmallVec; -use crate::common::pauth_fn_attrs; use crate::context::SimpleCx; use crate::errors::{PackedStackBackchainNeedsSoftfloat, SanitizerMemtagRequiresMte}; use crate::llvm::AttributePlace::Function; @@ -668,8 +665,9 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( } } - if sess.target.llvm_abiname == LlvmAbi::Pauthtest { - for &ptrauth_attr in pauth_fn_attrs() { + if sess.pointer_authentication() { + let cfg = sess.pointer_auth_config.as_ref().unwrap(); + for ptrauth_attr in cfg.fn_attrs() { to_add.push(llvm::CreateAttrString(cx.llcx, ptrauth_attr)); } } diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 880376742510b..14700266412dd 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -25,13 +25,12 @@ use rustc_middle::mono::Visibility; use rustc_middle::ty::TyCtxt; use rustc_session::config::{DebugInfo, Offload}; use rustc_span::Symbol; -use rustc_target::spec::{LlvmAbi, SanitizerSet}; +use rustc_target::spec::SanitizerSet; use super::ModuleLlvm; use crate::attributes; use crate::builder::Builder; use crate::builder::gpu_offload::OffloadGlobals; -use crate::common::pauth_fn_attrs; use crate::context::CodegenCx; use crate::llvm::{self, Value}; @@ -137,8 +136,9 @@ pub(crate) fn compile_codegen_unit( // FIXME(jchlanda) If it ever becomes necessary to ensure that all compiler // generated functions receive the ptrauth-* attributes, `declare_fn` or // `declare_raw_fn` could be used to provide those. - if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest { - for &ptrauth_attr in pauth_fn_attrs() { + if cx.sess().pointer_authentication() { + let cfg = cx.sess().pointer_auth_config.as_ref().unwrap(); + for ptrauth_attr in cfg.fn_attrs() { attrs.push(llvm::CreateAttrString(cx.llcx, ptrauth_attr)); } } @@ -158,28 +158,22 @@ pub(crate) fn compile_codegen_unit( cx.add_objc_module_flags(); } - if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest { - // FIXME(jchlanda): In LLVM/Clang, there are also `aarch64-elf-pauthabi-platform` - // and `aarch64-elf-pauthabi-version` module flags. These are emitted into the - // PAuth core info section of the resulting ELF, which the linker uses to enforce - // binary compatibility. - // - // We intentionally do not emit these flags now, since only a subset of features - // included in clang's pauthtest is currently supported. By default, the absence of - // this info is treated as compatible with any binary. - // - // Please note, that this would cause compatibility issues, specifically runtime - // crashes due to authentication failures (while compiling and linking - // successfully) when linking against binaries that support larger set of features - // (for example, signing of C++ member function pointers, virtual function - // pointers, virtual table pointers). - // - // Link to PAuth core info documentation: - // - if cx.sess().opts.unstable_opts.ptrauth_elf_got { + if cx.sess().pointer_authentication() { + let cfg = cx.sess().pointer_auth_config.as_ref().unwrap(); + + let aarch64_elf_pauthabi_version = + cfg.calculate_pauth_abi_version(&cx.sess().target); + if aarch64_elf_pauthabi_version != 0 { + cx.add_ptrauth_pauthabi_version_and_platform_flags( + aarch64_elf_pauthabi_version, + ); + } + if cfg.elf_got { cx.add_ptrauth_elf_got_flag(); } - cx.add_ptrauth_sign_personality_flag(); + if cx.sess().pointer_authentication_functions().is_some() { + cx.add_ptrauth_sign_personality_flag(); + } } // Finalize code coverage by injecting the coverage map. Note, the coverage map will diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 95380e4cb7533..af6c24018028a 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -26,7 +26,7 @@ use rustc_sanitizers::{cfi, kcfi}; use rustc_session::config::OptLevel; use rustc_span::Span; use rustc_target::callconv::{FnAbi, PassMode}; -use rustc_target::spec::{Arch, HasTargetSpec, LlvmAbi, SanitizerSet, Target}; +use rustc_target::spec::{Arch, HasTargetSpec, SanitizerSet, Target}; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -2039,7 +2039,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { llfn: &'ll Value, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, ) -> Option> { - if self.sess().target.llvm_abiname != LlvmAbi::Pauthtest { + if self.sess().pointer_authentication_functions().is_none() { return None; } // Pointer authentication support is currently limited to extern "C" calls; filter out other diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 1c26738b7cf9c..205e2e9a14701 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -16,7 +16,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::{Instance, TyCtxt}; use rustc_session::cstore::DllImport; -use rustc_target::spec::LlvmAbi; +use rustc_session::{PointerAuthAddressDiscriminator, PointerAuthSchema}; use tracing::debug; use crate::consts::{IsInitOrFini, IsStatic, const_alloc_to_llvm}; @@ -26,27 +26,13 @@ use crate::llvm::{ self, BasicBlock, ConstantInt, FALSE, TRUE, ToLlvmBool, Type, Value, const_ptr_auth, }; -#[inline] -pub(crate) fn pauth_fn_attrs() -> &'static [&'static str] { - // FIXME(jchlanda) This is not an exhaustive list of all `ptrauth`-related attributes, but only - // those currently supported. The list is expected to grow as additional functionality is - // implemented, particularly for C++ interoperability. - &[ - "aarch64-jump-table-hardening", - "ptrauth-indirect-gotos", - "ptrauth-calls", - "ptrauth-returns", - "ptrauth-auth-traps", - ] -} - pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( cx: &CodegenCx<'ll, '_>, instance: Instance<'tcx>, llfn: &'ll llvm::Value, - pac: PacMetadata, + schema: &PointerAuthSchema, ) -> &'ll llvm::Value { - if cx.sess().target.llvm_abiname != LlvmAbi::Pauthtest { + if cx.tcx.sess.pointer_authentication_functions().is_none() { return llfn; } @@ -68,16 +54,16 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( return llfn; } - let addr_diversity = match pac.addr_diversity { - AddressDiversity::None => None, - AddressDiversity::Real => Some(llfn), - AddressDiversity::Synthetic(val) => { + let addr_diversity = match schema.is_address_discriminated { + PointerAuthAddressDiscriminator::HardwareAddress(true) => Some(llfn), + PointerAuthAddressDiscriminator::HardwareAddress(false) => None, + PointerAuthAddressDiscriminator::Synthetic(val) => { let llval = cx.const_u64(val); let llty = cx.val_ty(llfn); Some(unsafe { llvm::LLVMConstIntToPtr(llval, llty) }) } }; - const_ptr_auth(llfn, pac.key, pac.disc, addr_diversity) + const_ptr_auth(llfn, schema.key as u32, schema.constant_discriminator as u64, addr_diversity) } /* @@ -331,7 +317,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { cv: Scalar, layout: abi::Scalar, llty: &'ll Type, - pac: Option, + schema: Option<&PointerAuthSchema>, ) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { @@ -387,7 +373,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { value } } - GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance, pac), + GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance, schema), GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 2552f4235e4ef..8f87acaf675a4 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_span::Symbol; -use rustc_target::spec::{Arch, LlvmAbi}; +use rustc_target::spec::Arch; use tracing::{debug, instrument, trace}; use crate::common::CodegenCx; @@ -32,6 +32,7 @@ pub(crate) enum IsStatic { No, } /// Indicates whether a symbol is part of `.init_array` or `.fini_array`. +#[derive(PartialEq)] pub(crate) enum IsInitOrFini { Yes, No, @@ -120,23 +121,14 @@ pub(crate) fn const_alloc_to_llvm<'ll>( as u64; let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx); - // Under pointer authentication, function pointers stored in init/fini arrays need special - // handling. - let pac_metadata = Some( - if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest - && matches!(is_init_fini, IsInitOrFini::Yes) - { - PacMetadata { - // Must correspond to ptrauth_key_init_fini_pointer from `ptrauth.h`. - key: 0, - // ptrauth_string_discriminator("init_fini") - disc: 0xd9d4, - addr_diversity: AddressDiversity::Synthetic(1), - } - } else { - PacMetadata::default() - }, - ); + let schema = if cx.sess().pointer_authentication() { + match is_init_fini { + IsInitOrFini::Yes => cx.sess().pointer_authentication_init_fini(), + IsInitOrFini::No => cx.sess().pointer_authentication_functions(), + } + } else { + None + }; llvals.push(cx.scalar_to_backend_with_pac( InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx), Scalar::Initialized { @@ -144,7 +136,7 @@ pub(crate) fn const_alloc_to_llvm<'ll>( valid_range: WrappingRange::full(pointer_size), }, cx.type_ptr_ext(address_space), - pac_metadata, + schema, )); next_offset = offset + pointer_size_bytes; } @@ -221,7 +213,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( let fn_sig = sig.with(*header); let fn_abi = cx.fn_abi_of_fn_ptr(fn_sig, ty::List::empty()); // Decide if the initializer needs to be signed - if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest + if cx.sess().pointer_authentication() && matches!(fn_sig.abi(), ExternAbi::C { .. } | ExternAbi::System { .. }) { should_sign = true; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 621f2cd3f9fc7..7ea30a5b4db6d 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -20,10 +20,10 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_session::Session; use rustc_session::config::{ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, FunctionReturn, PAuthKey, PacRet, }; +use rustc_session::{PointerAuthSchema, Session}; use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, sym}; use rustc_target::spec::{ Arch, CfgAbi, Env, FramePointer, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport, @@ -743,6 +743,29 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { ); } + pub(crate) fn add_ptrauth_pauthabi_version_and_platform_flags( + &self, + aarch64_elf_pauthabi_version: u32, + ) { + // NOTE: This must correspond to llvm's AARCH64_PAUTH_PLATFORM_LLVM_LINUX, as defined in + // /llvm/include/llvm/BinaryFormat/ELF.h. + // FIXME (jchlanda) extend possible values once we start supporting other platforms (for + // example: AARCH64_PAUTH_PLATFORM_BAREMETAL = 0x1); + const AARCH64_PAUTH_PLATFORM_LLVM_LINUX: u32 = 0x10000002; + llvm::add_module_flag_u32( + self.llmod, + llvm::ModuleFlagMergeBehavior::Error, + "aarch64-elf-pauthabi-platform", + AARCH64_PAUTH_PLATFORM_LLVM_LINUX, + ); + llvm::add_module_flag_u32( + self.llmod, + llvm::ModuleFlagMergeBehavior::Error, + "aarch64-elf-pauthabi-version", + aarch64_elf_pauthabi_version, + ); + } + // We do our best here to match what Clang does when compiling Objective-C natively. // See Clang's `CGObjCCommonMac::EmitImageInfo`: // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5085 @@ -887,7 +910,11 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { get_fn(self, instance) } - fn get_fn_addr(&self, instance: Instance<'tcx>, pac: Option) -> &'ll Value { + fn get_fn_addr( + &self, + instance: Instance<'tcx>, + pointer_auth_schema: Option<&PointerAuthSchema>, + ) -> &'ll Value { // When pointer authentication metadata is provided, `get_fn_addr` will // attempt to sign the pointer using LLVM's `ConstPtrAuth` constant // expression. @@ -901,8 +928,8 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { // , and comment in // builder's `ptrauth_operand_bundle`. let llfn = get_fn(self, instance); - match pac { - Some(pac) => common::maybe_sign_fn_ptr(self, instance, llfn, pac), + match pointer_auth_schema { + Some(schema) => common::maybe_sign_fn_ptr(self, instance, llfn, schema), None => llfn, } } @@ -954,7 +981,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { ty::List::empty(), DUMMY_SP, ), - Some(PacMetadata::default()), + tcx.sess.pointer_authentication_functions(), ), _ => { let name = name.unwrap_or("rust_eh_personality"); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f1ca2d7edc785..0d11f1e4fb69b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -28,7 +28,7 @@ use rustc_session::lint::builtin::DEPRECATED_LLVM_INTRINSIC; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate}; use rustc_target::callconv::PassMode; -use rustc_target::spec::{Arch, LlvmAbi}; +use rustc_target::spec::Arch; use tracing::debug; use crate::abi::FnAbiLlvmExt; @@ -37,7 +37,6 @@ use crate::builder::autodiff::{adjust_activity_to_abi, generate_enzyme_call}; use crate::builder::gpu_offload::{ OffloadKernelDims, gen_call_handling, gen_define_handling, register_offload, }; -use crate::common::pauth_fn_attrs; use crate::context::CodegenCx; use crate::declare::declare_raw_fn; use crate::errors::{ @@ -1697,9 +1696,12 @@ fn get_rust_try_fn<'a, 'll, 'tcx>( hir::Safety::Unsafe, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); - if cx.sess().target.llvm_abiname == LlvmAbi::Pauthtest { + + if cx.sess().pointer_authentication() { + let cfg = cx.sess().pointer_auth_config.as_ref().unwrap(); let attrs: Vec<&Attribute> = - pauth_fn_attrs().iter().map(|name| llvm::CreateAttrString(cx.llcx, name)).collect(); + cfg.fn_attrs().into_iter().map(|name| llvm::CreateAttrString(cx.llcx, name)).collect(); + let (_ty, rust_try_fn) = rust_try; crate::attributes::apply_to_llfn(rust_try_fn, AttributePlace::Function, &attrs); } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 028cd8c792349..43d5e312c6b40 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -494,7 +494,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return None; } - let main_llfn = cx.get_fn_addr(instance, Some(PacMetadata::default())); + let main_llfn = cx.get_fn_addr(instance, cx.sess().pointer_authentication_functions()); let entry_fn = create_entry_fn::(cx, main_llfn, main_def_id, entry_type); return Some(entry_fn); @@ -555,7 +555,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx.tcx().mk_args(&[main_ret_ty.into()]), DUMMY_SP, ); - let start_fn = cx.get_fn_addr(start_instance, Some(PacMetadata::default())); + let start_fn = + cx.get_fn_addr(start_instance, cx.sess().pointer_authentication_functions()); let i8_ty = cx.type_i8(); let arg_sigpipe = bx.const_u8(sigpipe); diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 3a2ff3ab5d2ae..ae72258a87c86 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -119,7 +119,7 @@ pub(crate) fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let instance = ty::Instance::mono(tcx, def_id); ( bx.fn_abi_of_instance(instance, ty::List::empty()), - bx.get_fn_addr(instance, Some(PacMetadata::default())), + bx.get_fn_addr(instance, tcx.sess.pointer_authentication_functions()), instance, ) } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index cf59a0aeb24ab..fba0cff0e6e14 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -686,7 +686,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => ( false, - bx.get_fn_addr(drop_fn, Some(PacMetadata::default())), + bx.get_fn_addr(drop_fn, bx.sess().pointer_authentication_functions()), bx.fn_abi_of_instance(drop_fn, ty::List::empty()), drop_fn, ), @@ -1102,7 +1102,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) .unwrap(); - (None, Some(bx.get_fn_addr(instance, Some(PacMetadata::default())))) + ( + None, + Some(bx.get_fn_addr( + instance, + bx.sess().pointer_authentication_functions(), + )), + ) } _ => (Some(instance), None), } @@ -1415,7 +1421,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let fn_ptr = match (instance, llfn) { - (Some(instance), None) => bx.get_fn_addr(instance, Some(PacMetadata::default())), + (Some(instance), None) => { + bx.get_fn_addr(instance, bx.sess().pointer_authentication_functions()) + } (_, Some(llfn)) => llfn, _ => span_bug!(fn_span, "no instance or llfn for call"), }; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 9719b9297af02..077d724997441 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -518,7 +518,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Immediate( bx.get_fn_addr( instance, - Some(PacMetadata::default()), + bx.sess().pointer_authentication_functions(), ), ) } @@ -537,7 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Immediate( bx.cx().get_fn_addr( instance, - Some(PacMetadata::default()), + bx.sess().pointer_authentication_functions(), ), ) } @@ -759,7 +759,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def: ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(def_id)), args: ty::GenericArgs::empty(), }; - let fn_ptr = bx.get_fn_addr(instance, Some(PacMetadata::default())); + let fn_ptr = + bx.get_fn_addr(instance, bx.sess().pointer_authentication_functions()); let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); let fn_ty = bx.fn_decl_backend_type(fn_abi); let fn_attrs = if bx.tcx().def_kind(instance.def_id()).has_codegen_attrs() { diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 20738ba79e9fb..b4eba38d39c19 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -1,8 +1,8 @@ use rustc_abi as abi; use rustc_middle::mir::interpret::Scalar; +use rustc_session::PointerAuthSchema; use super::BackendTypes; -use crate::traits::PacMetadata; pub trait ConstCodegenMethods: BackendTypes { // Constant constructors @@ -47,7 +47,7 @@ pub trait ConstCodegenMethods: BackendTypes { cv: Scalar, layout: abi::Scalar, llty: Self::Type, - pac: Option, + schema: Option<&PointerAuthSchema>, ) -> Self::Value; fn const_ptr_byte_offset(&self, val: Self::Value, offset: abi::Size) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index ecef986b55855..add7128a2974b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -2,40 +2,11 @@ use std::cell::RefCell; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::{self, Instance, Ty}; -use rustc_session::Session; +use rustc_session::{PointerAuthSchema, Session}; use rustc_span::Symbol; use super::BackendTypes; -/// Strategy for incorporating address-based diversity into PAC computation. -#[derive(Default)] -pub enum AddressDiversity { - /// No address diversity is applied. - #[default] - None, - /// Use the actual memory address for diversification. - Real, - /// Use a fixed synthetic value instead of the real address, - /// i.e. `1` is used for `.init_array` / `.fini_array`. - Synthetic(u64), -} - -/// Metadata used for pointer authentication. -pub struct PacMetadata { - /// The PAC key to use. - pub key: u32, - /// Discriminator value used to diversify the PAC. - pub disc: u64, - /// Controls how address diversity is applied when computing the PAC. - pub addr_diversity: AddressDiversity, -} - -impl Default for PacMetadata { - fn default() -> Self { - PacMetadata { key: 0, disc: 0, addr_diversity: AddressDiversity::default() } - } -} - pub trait MiscCodegenMethods<'tcx>: BackendTypes { fn vtables( &self, @@ -48,7 +19,11 @@ pub trait MiscCodegenMethods<'tcx>: BackendTypes { ) { } fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function; - fn get_fn_addr(&self, instance: Instance<'tcx>, pac: Option) -> Self::Value; + fn get_fn_addr( + &self, + instance: Instance<'tcx>, + pointer_auth_schema: Option<&PointerAuthSchema>, + ) -> Self::Value; fn eh_personality(&self) -> Self::Function; fn sess(&self) -> &Session; fn set_frame_pointer_type(&self, llfn: Self::Function); diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index ed2dad5a510cd..f46d07ea5008e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -42,7 +42,7 @@ pub use self::coverageinfo::CoverageInfoBuilderMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; pub use self::declare::PreDefineCodegenMethods; pub use self::intrinsic::IntrinsicCallBuilderMethods; -pub use self::misc::{AddressDiversity, MiscCodegenMethods, PacMetadata}; +pub use self::misc::MiscCodegenMethods; pub use self::statics::{StaticBuilderMethods, StaticCodegenMethods}; pub use self::type_::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, DerivedTypeCodegenMethods, diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index c7c37d30dd546..0ab9782c69356 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -461,6 +461,14 @@ language_item_table! { MemCmp, sym::memcmp_fn, memcmp_fn, Target::ForeignFn, GenericRequirement::None; Bcmp, sym::bcmp_fn, bcmp_fn, Target::ForeignFn, GenericRequirement::None; StrLen, sym::strlen_fn, strlen_fn, Target::ForeignFn, GenericRequirement::None; + Open, sym::open_fn, open_fn, Target::ForeignFn, GenericRequirement::None; + Read, sym::read_fn, read_fn, Target::ForeignFn, GenericRequirement::None; + Write, sym::write_fn, write_fn, Target::ForeignFn, GenericRequirement::None; + Close, sym::close_fn, close_fn, Target::ForeignFn, GenericRequirement::None; + Malloc, sym::malloc_fn, malloc_fn, Target::ForeignFn, GenericRequirement::None; + Realloc, sym::realloc_fn, realloc_fn, Target::ForeignFn, GenericRequirement::None; + Free, sym::free_fn, free_fn, Target::ForeignFn, GenericRequirement::None; + Exit, sym::exit_fn, exit_fn, Target::ForeignFn, GenericRequirement::None; } /// The requirement imposed on the generics of a lang item diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index a2541089a530b..be3e2424d1782 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -45,4 +45,12 @@ weak_only_lang_items! { MemCmp, Bcmp, StrLen, + Open, + Read, + Write, + Close, + Malloc, + Realloc, + Free, + Exit, } diff --git a/compiler/rustc_lint/src/runtime_symbols.rs b/compiler/rustc_lint/src/runtime_symbols.rs index 5f987f9ab29cc..cfed2997c527e 100644 --- a/compiler/rustc_lint/src/runtime_symbols.rs +++ b/compiler/rustc_lint/src/runtime_symbols.rs @@ -11,7 +11,7 @@ use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `invalid_runtime_symbol_definitions` lint checks the signature of items whose - /// symbol name is a runtime symbol expected by `core` differs significantly from the + /// symbol name is a runtime symbol expected by `core` or `std` differs significantly from the /// expected signature (like mismatch ABI, mismatch C variadics, mismatch argument count, /// missing return type, ...). /// @@ -31,7 +31,8 @@ declare_lint! { /// standard-library facility or undefined behavior may occur. /// /// The symbols currently checked are `memcpy`, `memmove`, `memset`, `memcmp`, - /// `bcmp` and `strlen`. + /// `bcmp`, `strlen`, as well as the following POSIX symbols: `open`, `read`, `write` + /// `close`, `malloc`, `realloc`, `free` and `exit`. /// /// [^1]: https://doc.rust-lang.org/core/index.html#how-to-use-the-core-library pub INVALID_RUNTIME_SYMBOL_DEFINITIONS, @@ -41,7 +42,7 @@ declare_lint! { declare_lint! { /// The `suspicious_runtime_symbol_definitions` lint checks the signature of items whose - /// symbol name is a runtime symbol expected by `core`. + /// symbol name is a runtime symbol expected by `core` or `std`. /// /// ### Example /// @@ -61,7 +62,8 @@ declare_lint! { /// standard-library facility or undefined behavior may occur. /// /// The symbols currently checked are `memcpy`, `memmove`, `memset`, `memcmp`, - /// `bcmp` and `strlen`. + /// `bcmp`, `strlen`, as well as the following POSIX symbols: `open`, `read`, `write` + /// `close`, `malloc`, `realloc`, `free` and `exit`. /// /// [^1]: https://doc.rust-lang.org/core/index.html#how-to-use-the-core-library pub SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS, @@ -72,12 +74,22 @@ declare_lint! { declare_lint_pass!(RuntimeSymbols => [INVALID_RUNTIME_SYMBOL_DEFINITIONS, SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS]); static EXPECTED_SYMBOLS: &[ExpectedSymbol] = &[ + // `core` symbols ExpectedSymbol { symbol: "memcpy", lang: LanguageItems::memcpy_fn }, ExpectedSymbol { symbol: "memmove", lang: LanguageItems::memmove_fn }, ExpectedSymbol { symbol: "memset", lang: LanguageItems::memset_fn }, ExpectedSymbol { symbol: "memcmp", lang: LanguageItems::memcmp_fn }, ExpectedSymbol { symbol: "bcmp", lang: LanguageItems::bcmp_fn }, ExpectedSymbol { symbol: "strlen", lang: LanguageItems::strlen_fn }, + // POSIX symbols + ExpectedSymbol { symbol: "open", lang: LanguageItems::open_fn }, + ExpectedSymbol { symbol: "read", lang: LanguageItems::read_fn }, + ExpectedSymbol { symbol: "write", lang: LanguageItems::write_fn }, + ExpectedSymbol { symbol: "close", lang: LanguageItems::close_fn }, + ExpectedSymbol { symbol: "malloc", lang: LanguageItems::malloc_fn }, + ExpectedSymbol { symbol: "realloc", lang: LanguageItems::realloc_fn }, + ExpectedSymbol { symbol: "free", lang: LanguageItems::free_fn }, + ExpectedSymbol { symbol: "exit", lang: LanguageItems::exit_fn }, ]; #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f500382719544..8ed01315ade53 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1602,6 +1602,48 @@ pub struct BranchProtection { pub gcs: bool, } +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] +pub enum PointerAuthOption { + // See and Clang's command line reference: + // + // for the origin and meaning of the enum values. + // tidy-alphabetical-start + Aarch64JumpTableHardening, + AuthTraps, + Calls, + ElfGot, + FunctionPointerTypeDiscrimination, + IndirectGotos, + InitFini, + InitFiniAddressDiscrimination, + Intrinsics, + ReturnAddresses, + TypeInfoVTPtrDisc, + VTPtrAddrDisc, + VTPtrTypeDisc, + // tidy-alphabetical-end +} +impl PointerAuthOption { + pub fn parse(s: &str) -> Option { + match s { + "aarch64-jump-table-hardening" => Some(Self::Aarch64JumpTableHardening), + "auth-traps" => Some(Self::AuthTraps), + "calls" => Some(Self::Calls), + "elf-got" => Some(Self::ElfGot), + "function-pointer-type-discrimination" => Some(Self::FunctionPointerTypeDiscrimination), + "indirect-gotos" => Some(Self::IndirectGotos), + "init-fini" => Some(Self::InitFini), + "init-fini-address-discrimination" => Some(Self::InitFiniAddressDiscrimination), + "intrinsics" => Some(Self::Intrinsics), + "return-addresses" => Some(Self::ReturnAddresses), + "typeinfo-vt-ptr-discrimination" => Some(Self::TypeInfoVTPtrDisc), + "vt-ptr-addr-discrimination" => Some(Self::VTPtrAddrDisc), + "vt-ptr-type-discrimination" => Some(Self::VTPtrTypeDisc), + _ => None, + } + } +} + pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg { // First disallow some configuration given on the command line cfg::disallow_cfgs(sess, &user_cfg); @@ -3098,8 +3140,8 @@ pub(crate) mod dep_tracking { CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentMcount, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, - OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, - ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, + OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, PointerAuthOption, + Polonius, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; @@ -3207,6 +3249,7 @@ pub(crate) mod dep_tracking { Align, CodegenRetagOptions, RustcVersion, + PointerAuthOption, ); impl DepTrackingHash for (T1, T2) diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index 31627887b662b..d1989609cefe2 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -381,6 +381,20 @@ pub(crate) struct StackProtectorNotSupportedForTarget<'a> { pub(crate) target_triple: &'a TargetTuple, } +#[derive(Diagnostic)] +#[diag("function pointer type discrimination is not supported")] +pub(crate) struct PointerAuthenticationTypeDiscriminationNotSupportedForTarget<'a> { + pub(crate) target_triple: &'a TargetTuple, +} + +#[derive(Diagnostic)] +#[diag( + "`-Z pointer-authentication` is not supported for target {$target_triple} and will be ignored" +)] +pub(crate) struct PointerAuthenticationNotSupportedForTarget<'a> { + pub(crate) target_triple: &'a TargetTuple, +} + #[derive(Diagnostic)] #[diag( "`-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored" diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d508c963791d4..6f3a505c2c26f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -771,6 +771,7 @@ mod desc { pub(crate) const parse_list: &str = "a space-separated list of strings"; pub(crate) const parse_list_with_polarity: &str = "a comma-separated list of strings, with elements beginning with + or -"; + pub(crate) const parse_pointer_authentication_list_with_polarity: &str = "a comma-separated list of options, each of the form `+` or `-`, where `` is one of: `aarch64-jump-table-hardening`, `auth-traps`, `calls`, `elf-got`, `function-pointer-type-discrimination`, `indirect-gotos`, `init-fini`, `init-fini-address-discrimination`, `intrinsics`, `return-addresses`, `typeinfo-vt-ptr-discrimination`, `vt-ptr-addr-discrimination` or `vt-ptr-type-discrimination`"; pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintTAFn`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `PrintModFinal`, `PrintPasses`, `NoPostopt`, `LooseTypes`, `Inline`, `NoTT`"; pub(crate) const parse_offload: &str = "a comma separated list of settings: `Host=`, `Device`, `Test`"; @@ -1036,6 +1037,37 @@ pub mod parse { } } + pub(crate) fn parse_pointer_authentication_list_with_polarity( + slot: &mut Vec<(PointerAuthOption, bool)>, + v: Option<&str>, + ) -> bool { + let Some(s) = v else { + return false; + }; + + let mut map = BTreeMap::::new(); + + for item in s.split(',') { + let Some(name) = item.strip_prefix(&['+', '-'][..]) else { + return false; + }; + + let Some(opt) = PointerAuthOption::parse(name) else { + return false; + }; + + let enabled = item.starts_with('+'); + + // Last occurrence wins. + map.insert(opt, enabled); + } + + slot.clear(); + slot.extend(map); + + true + } + pub(crate) fn parse_fmt_debug(opt: &mut FmtDebug, v: Option<&str>) -> bool { *opt = match v { Some("full") => FmtDebug::Full, @@ -2626,6 +2658,26 @@ options! { "whether to use the PLT when calling into shared libraries; only has effect for PIC code on systems with ELF binaries (default: PLT is disabled if full relro is enabled on x86_64)"), + pointer_authentication: Vec<(PointerAuthOption, bool)> = ( + Vec::new(), + parse_pointer_authentication_list_with_polarity, + [TRACKED] + { TARGET_MODIFIER: PointerAuthentication }, + "A comma-separated list of pointer authentication options, each prefixed with `+` (enable) or `-` (disable). Available options: + `aarch64-jump-table-hardening` - enable hardened lowering for jump-table dispatch + `auth-traps` - trap immediately on pointer authentication failure + `calls` - enable signing and authentication of all indirect calls + `elf-got` - enable authentication of pointers from GOT (ELF only) + `function-pointer-type-discrimination` - enable type discrimination on C function pointers + `indirect-gotos` - enable signing and authentication of indirect goto targets + `init-fini` - enable signing of function pointers in init/fini arrays + `init-fini-address-discrimination` - enable address discrimination in init/fini arrays + `intrinsics` - pointer authentication intrinsics + `return-addresses` - enable signing and authentication of return addresses + `typeinfo-vt-ptr-discrimination - incorporate type and address discrimination in authenticated vtable pointers for std::type_info + `vt-ptr-addr-discrimination - incorporate address discrimination in authenticated vtable pointers + `vt-ptr-type-discrimination - incorporate type discrimination in authenticated vtable pointers + Example: `-Zpointer-authentication=+calls,-init-fini`."), polonius: Polonius = (Polonius::default(), parse_polonius, [TRACKED], "enable polonius-based borrow-checker (default: no)"), pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED], @@ -2659,7 +2711,6 @@ options! { "use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"), profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED], "name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)"), - ptrauth_elf_got: bool = (false, parse_bool, [TRACKED], "enable signing of ELF GOT entries"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing (default: no)"), randomize_layout: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b7c0923163b4d..733470a7e0471 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -39,7 +39,7 @@ pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, Varian use crate::config::{ self, Cfg, CheckCfg, CoverageLevel, CoverageOptions, CrateType, DebugInfo, ErrorOutputType, FunctionReturn, Input, InstrumentCoverage, InstrumentMcount, OptLevel, OutFileName, OutputType, - SwitchWithOptPath, + PointerAuthOption, SwitchWithOptPath, }; use crate::filesearch::FileSearch; use crate::lint::LintId; @@ -85,6 +85,245 @@ pub trait DynLintStore: Any + DynSync + DynSend { fn lint_groups_iter(&self) -> Box + '_>; } +/// Hardware pointer-signing keys in ARM8.3. +/// These values are the same as used in ptrauth.h. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PointerAuthARM8_3Key { + ASIA = 0, + ASIB = 1, + ASDA = 2, + ASDB = 3, +} + +/// Forms of extra discrimination. +pub enum PointerAuthDiscrimination { + /// No additional discrimination. + None, + /// Include a hash of the entity's type. + Type, + /// Include a hash of the entity's identity. + Decl, + /// Discriminate using a constant value. + Constant, +} + +/// Types of address discrimination. +pub enum PointerAuthAddressDiscriminator { + /// Enable/disable hardware address discrimination. + HardwareAddress(bool), + /// Use a synthetic value. For instance init/fini entries can not the address of the arrays, + /// they must use a synthetic value of `1`. + Synthetic(u64), +} + +pub struct PointerAuthSchema { + pub is_address_discriminated: PointerAuthAddressDiscriminator, + pub discrimination_kind: PointerAuthDiscrimination, + pub key: PointerAuthARM8_3Key, + pub constant_discriminator: u16, +} +impl PointerAuthSchema { + pub fn function_pointers_default(target: &Target) -> Self { + assert!(target.cfg_abi == CfgAbi::Pauthtest); + return Self { + is_address_discriminated: PointerAuthAddressDiscriminator::HardwareAddress(false), + discrimination_kind: PointerAuthDiscrimination::None, + key: PointerAuthARM8_3Key::ASIA, + constant_discriminator: 0, + }; + } + pub fn init_fini_default(target: &Target) -> Self { + assert!(target.cfg_abi == CfgAbi::Pauthtest); + return Self { + is_address_discriminated: PointerAuthAddressDiscriminator::Synthetic(1), + discrimination_kind: PointerAuthDiscrimination::None, + key: PointerAuthARM8_3Key::ASIA, + // ptrauth_string_discriminator("init_fini") + constant_discriminator: 0xd9d4, + }; + } +} + +pub struct PointerAuthConfig { + /// Should return addresses be authenticated? + pub return_addresses: bool, + /// Do authentication failures cause a trap? + pub auth_traps: bool, + /// Do indirect goto label addresses need to be authenticated? + pub indirect_gotos: bool, + /// Should ELF GOT entries be signed? + pub elf_got: bool, + /// Use hardened lowering for jump-table dispatch? + pub aarch64_jump_table_hardening: bool, + /// The ABI for C function pointers. + pub function_pointers: Option, + /// The ABI for function addresses in .init_array and .fini_array + pub init_fini: Option, + /// Use of pointer authentication intrinsics. + pub intrinsics: bool, + /// The following are used only for compatibility with C++ and control over generated abi + /// version. They do not control Rust code generation. + pub typeinfo_vt_ptr_discrimination: bool, + pub vt_ptr_addr_discrimination: bool, + pub vt_ptr_type_discrimination: bool, +} +impl PointerAuthConfig { + fn default(target: &Target) -> Self { + assert!(target.cfg_abi == CfgAbi::Pauthtest); + return Self { + return_addresses: true, + auth_traps: true, + indirect_gotos: true, + elf_got: false, + aarch64_jump_table_hardening: true, + function_pointers: Some(PointerAuthSchema::function_pointers_default(target)), + init_fini: Some(PointerAuthSchema::init_fini_default(target)), + intrinsics: true, + typeinfo_vt_ptr_discrimination: true, + vt_ptr_addr_discrimination: true, + vt_ptr_type_discrimination: true, + }; + } + pub fn calculate_pauth_abi_version(&self, target: &Target) -> u32 { + assert!(target.cfg_abi == CfgAbi::Pauthtest); + // Bit positions of version flags for AARCH64_PAUTH_PLATFORM_LLVM_LINUX. + // NOTE: The enum values must stay in sync with clang, see: + // /llvm/include/llvm/BinaryFormat/ELF.h + // + // We do not expect to use C++ virtual dispatch, but enable these flags + // for compatibility with C++ code. Intrinsics are also always enabled. + // + // Link to PAuth core info documentation: + // + const INTRINSICS: u32 = 0; + const CALLS: u32 = 1; + const RETURNS: u32 = 2; + const AUTHTRAPS: u32 = 3; + const VT_PTR_ADDR_DISCR: u32 = 4; + const VT_PTR_TYPE_DISCR: u32 = 5; + const INIT_FINI: u32 = 6; + const INIT_FINI_ADDR_DISC: u32 = 7; + const GOT: u32 = 8; + const GOTOS: u32 = 9; + const TYPEINFO_VT_PTR_DISCR: u32 = 10; + // FIXME(jchlanda) We don't yet support function pointer type discrimination. + // const FPTR_TYPE_DISCR: u32 = 11; + + let pauth_abi_version: u32 = (u32::from(self.intrinsics) << INTRINSICS) + | (u32::from(self.function_pointers.is_some()) << CALLS) + | (u32::from(self.return_addresses) << RETURNS) + | (u32::from(self.auth_traps) << AUTHTRAPS) + | (u32::from(self.vt_ptr_addr_discrimination) << VT_PTR_ADDR_DISCR) + | (u32::from(self.vt_ptr_type_discrimination) << VT_PTR_TYPE_DISCR) + | (u32::from(self.init_fini.is_some()) << INIT_FINI) + | (u32::from(self.init_fini.as_ref().is_some_and(|schema| { + matches!( + schema.is_address_discriminated, + PointerAuthAddressDiscriminator::HardwareAddress(true) + | PointerAuthAddressDiscriminator::Synthetic(_) + ) + })) << INIT_FINI_ADDR_DISC) + | (u32::from(self.elf_got) << GOT) + | (u32::from(self.indirect_gotos) << GOTOS) + | (u32::from(self.typeinfo_vt_ptr_discrimination) << TYPEINFO_VT_PTR_DISCR); + + pauth_abi_version + } + pub fn from_raw(raw: &[(PointerAuthOption, bool)], target: &Target) -> Option { + if target.cfg_abi != CfgAbi::Pauthtest { + return None; + } + + let mut cfg = Self::default(target); + if raw.is_empty() { + return Some(cfg); + } + + for (opt, enabled) in raw { + match opt { + PointerAuthOption::Calls => { + if *enabled { + cfg.function_pointers.get_or_insert_with(|| { + PointerAuthSchema::function_pointers_default(target) + }); + } else { + cfg.function_pointers = None; + } + } + PointerAuthOption::FunctionPointerTypeDiscrimination => { + if *enabled { + let schema = cfg.function_pointers.get_or_insert_with(|| { + PointerAuthSchema::function_pointers_default(target) + }); + schema.discrimination_kind = PointerAuthDiscrimination::Type; + } else if let Some(schema) = &mut cfg.function_pointers { + schema.discrimination_kind = PointerAuthDiscrimination::None; + } + } + PointerAuthOption::ReturnAddresses => cfg.return_addresses = *enabled, + PointerAuthOption::AuthTraps => cfg.auth_traps = *enabled, + PointerAuthOption::IndirectGotos => cfg.indirect_gotos = *enabled, + PointerAuthOption::ElfGot => cfg.elf_got = *enabled, + PointerAuthOption::Aarch64JumpTableHardening => { + cfg.aarch64_jump_table_hardening = *enabled + } + PointerAuthOption::InitFini => { + if *enabled { + cfg.init_fini + .get_or_insert_with(|| PointerAuthSchema::init_fini_default(target)); + } else { + cfg.init_fini = None; + } + } + PointerAuthOption::InitFiniAddressDiscrimination => { + if *enabled { + let schema = cfg + .init_fini + .get_or_insert_with(|| PointerAuthSchema::init_fini_default(target)); + schema.is_address_discriminated = + PointerAuthAddressDiscriminator::HardwareAddress(true); + } else if let Some(schema) = &mut cfg.init_fini { + schema.is_address_discriminated = + PointerAuthAddressDiscriminator::Synthetic(1); + } + } + + PointerAuthOption::Intrinsics => cfg.intrinsics = *enabled, + PointerAuthOption::TypeInfoVTPtrDisc => { + cfg.typeinfo_vt_ptr_discrimination = *enabled + } + PointerAuthOption::VTPtrAddrDisc => cfg.vt_ptr_addr_discrimination = *enabled, + PointerAuthOption::VTPtrTypeDisc => cfg.vt_ptr_type_discrimination = *enabled, + } + } + + Some(cfg) + } + pub fn fn_attrs(&self) -> Vec<&'static str> { + // FIXME(jchlanda) This is not an exhaustive list of all `ptrauth`-related attributes, but only + // those currently supported. The list is expected to grow as additional functionality is + // implemented, particularly for C++ interoperability. + let mut attrs = vec![]; + if self.aarch64_jump_table_hardening { + attrs.push("aarch64-jump-table-hardening"); + } + if self.auth_traps { + attrs.push("ptrauth-auth-traps"); + } + if self.function_pointers.is_some() { + attrs.push("ptrauth-calls"); + } + if self.indirect_gotos { + attrs.push("ptrauth-indirect-gotos"); + } + if self.return_addresses { + attrs.push("ptrauth-returns"); + } + + attrs + } +} + /// Represents the data associated with a compilation /// session for a single crate. pub struct Session { @@ -185,6 +424,9 @@ pub struct Session { /// Whether the test harness removed a user-written `#[rustc_main]` attribute /// while generating the synthetic test entry point. pub removed_rustc_main_attr: AtomicBool, + + /// Config specifying targets' pointer authentication preference. + pub pointer_auth_config: Option, } #[derive(Clone, Copy)] @@ -946,6 +1188,18 @@ impl Session { pub fn sanitizers(&self) -> SanitizerSet { return self.opts.unstable_opts.sanitizer | self.target.options.default_sanitizers; } + + pub fn pointer_authentication(&self) -> bool { + self.pointer_auth_config.is_some() + } + + pub fn pointer_authentication_functions(&self) -> Option<&PointerAuthSchema> { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.function_pointers.as_ref()) + } + + pub fn pointer_authentication_init_fini(&self) -> Option<&PointerAuthSchema> { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.init_fini.as_ref()) + } } // JUSTIFICATION: part of session construction @@ -1105,6 +1359,9 @@ pub fn build_session( let timings = TimingSectionHandler::new(sopts.json_timings); + let pointer_auth_config: Option = + PointerAuthConfig::from_raw(&sopts.unstable_opts.pointer_authentication, &target); + let sess = Session { target, host, @@ -1139,6 +1396,7 @@ pub fn build_session( mir_opt_bisect_eval_count: AtomicUsize::new(0), used_features: Lock::default(), removed_rustc_main_attr: AtomicBool::new(false), + pointer_auth_config, }; validate_commandline_args_with_session_available(&sess); @@ -1171,6 +1429,27 @@ fn validate_commandline_args_with_session_available(sess: &Session) { sess.dcx().emit_err(diagnostics::LinkerPluginToWindowsNotSupported); } + if sess + .pointer_auth_config + .as_ref() + .and_then(|cfg| cfg.function_pointers.as_ref()) + .is_some_and(|schema| matches!(schema.discrimination_kind, PointerAuthDiscrimination::Type)) + { + sess.dcx().emit_err( + diagnostics::PointerAuthenticationTypeDiscriminationNotSupportedForTarget { + target_triple: &sess.opts.target_triple, + }, + ); + } + + if sess.target.cfg_abi != CfgAbi::Pauthtest + && !sess.opts.unstable_opts.pointer_authentication.is_empty() + { + sess.dcx().emit_warn(diagnostics::PointerAuthenticationNotSupportedForTarget { + target_triple: &sess.opts.target_triple, + }); + } + // Make sure that any given profiling data actually exists so LLVM can't // decide to silently skip PGO. if let Some(ref path) = sess.opts.cg.profile_use { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3b44015b4f452..de090531a6192 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -616,6 +616,7 @@ symbols! { clone_closures, clone_fn, clone_from, + close_fn, closure, closure_lifetime_binder, closure_to_fn_coercion, @@ -901,6 +902,7 @@ symbols! { exhaustive_integer_patterns, exhaustive_patterns, existential_type, + exit_fn, exp2f16, exp2f32, exp2f64, @@ -1012,6 +1014,7 @@ symbols! { format_unsafe_arg, fp, framework, + free_fn, freeze, freeze_impls, freg, @@ -1254,6 +1257,7 @@ symbols! { macro_vis_matcher, macros_in_extern, main, + malloc_fn, managed_boxes, manually_drop, map, @@ -1479,6 +1483,7 @@ symbols! { on_unmatched_args, opaque, opaque_module_name_placeholder: "", + open_fn, ops, opt_out_copy, optimize, @@ -1663,9 +1668,11 @@ symbols! { raw_identifiers, raw_ref_op, re_rebalance_coherence, + read_fn, read_via_copy, readonly, realloc, + realloc_fn, realtime, reason, reborrow, @@ -2372,6 +2379,7 @@ symbols! { write_box_via_move, write_bytes, write_fmt, + write_fn, write_macro, write_str, write_via_move, diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 9c5b487d1cbf0..66d9c9da27180 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -322,6 +322,7 @@ #![feature(borrowed_buf_init)] #![feature(bstr)] #![feature(bstr_internals)] +#![feature(c_size_t)] #![feature(can_vector)] #![feature(cast_maybe_uninit)] #![feature(char_internals)] diff --git a/library/std/src/sys/alloc/unix.rs b/library/std/src/sys/alloc/unix.rs index d6de8bf28c44c..b9c5dfd24396f 100644 --- a/library/std/src/sys/alloc/unix.rs +++ b/library/std/src/sys/alloc/unix.rs @@ -2,6 +2,25 @@ use super::{MIN_ALIGN, realloc_fallback}; use crate::alloc::Layout; use crate::ptr; +// Used by rustc for checking the definitions of other function with the same symbol names +// +// See the `invalid_runtime_symbols_definitions` lint. +#[cfg(not(test))] +mod runtime_symbols { + use core::ffi::{c_size_t, c_void}; + + unsafe extern "C" { + #[lang = "malloc_fn"] + fn malloc(size: c_size_t) -> *mut c_void; + + #[lang = "realloc_fn"] + fn realloc(ptr: *mut c_void, size: c_size_t) -> *mut c_void; + + #[lang = "free_fn"] + fn free(ptr: *mut c_void); + } +} + #[inline] pub unsafe fn alloc(layout: Layout) -> *mut u8 { // jemalloc provides alignment less than MIN_ALIGN for small allocations. diff --git a/library/std/src/sys/exit.rs b/library/std/src/sys/exit.rs index 53fb92ba077e0..c4fa3af803071 100644 --- a/library/std/src/sys/exit.rs +++ b/library/std/src/sys/exit.rs @@ -68,6 +68,25 @@ cfg_select! { } } +#[cfg(not(test))] +cfg_select! { + any( + target_family = "unix", + target_os = "wasi", + ) => { + // Used by rustc for checking the definitions of other function with the same symbol names + // + // See the `invalid_runtime_symbols_definitions` lint. + mod runtime_symbols { + unsafe extern "C" { + #[lang = "exit_fn"] + fn exit(status: core::ffi::c_int) -> !; + } + } + } + _ => {} +} + pub fn exit(code: i32) -> ! { cfg_select! { target_os = "hermit" => { diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 7283e8f710c55..cadbf1a21aa8f 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -102,6 +102,28 @@ use crate::sys::weak::weak; use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, cvt, cvt_r}; use crate::{mem, ptr}; +// Used by rustc for checking the definitions of other function with the same symbol names +// +// See the `invalid_runtime_symbols_definitions` lint. +#[cfg(not(test))] +mod runtime_symbols { + use core::ffi::{c_char, c_int, c_size_t, c_ssize_t, c_void}; + + unsafe extern "C" { + #[lang = "open_fn"] + fn open(pathname: *const c_char, flags: c_int, ...) -> c_int; + + #[lang = "read_fn"] + fn read(fd: c_int, buf: *mut c_void, count: c_size_t) -> c_ssize_t; + + #[lang = "write_fn"] + fn write(fd: c_int, buf: *const c_void, count: c_size_t) -> c_ssize_t; + + #[lang = "close_fn"] + fn close(fd: c_int) -> c_int; + } +} + pub struct File(FileDesc); // FIXME: This should be available on Linux with all `target_env`. diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 63e443bac2363..1310255de3ca4 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -9,6 +9,7 @@ use std::fs::{self, OpenOptions, TryLockError}; use std::io::{self, BufRead, BufReader, IsTerminal, Read, Write}; use std::path::Path; use std::str::FromStr; +use std::sync::Once; use std::time::Instant; use std::{env, process}; @@ -27,16 +28,23 @@ fn main() { let _start_time = Instant::now(); - // Always print backtraces to provide richer errors, to help debug hard-to-reproduce panics - // when the user didn't specify RUST_BACKTRACE - if std::env::var("RUST_BACKTRACE").is_err() { - unsafe { - std::env::set_var("RUST_BACKTRACE", "1"); - } - } - let default_panic_hook = std::panic::take_hook(); std::panic::set_hook(Box::new(move |info| { + static BACKTRACE_LOCK: Once = Once::new(); + + // Always print backtraces to provide richer errors, to help debug hard-to-reproduce panics + // when the user didn't specify RUST_BACKTRACE + // Note that we only override this variable in the panic handler, because bootstrap might + // manually capture backtraces when a command is executed, and in that case we do not want + // to always force backtraces. + BACKTRACE_LOCK.call_once(|| { + if std::env::var("RUST_BACKTRACE").is_err() { + unsafe { + std::env::set_var("RUST_BACKTRACE", "1"); + } + } + }); + default_panic_hook(info); StepStack::with_current(|stack| { eprintln!("\nBootstrap has panicked, currently active steps:"); diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-linux-pauthtest.md b/src/doc/rustc/src/platform-support/aarch64-unknown-linux-pauthtest.md index 558bc409e08d2..e0f11c7800dcd 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-linux-pauthtest.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-linux-pauthtest.md @@ -356,6 +356,82 @@ linker = "/aarch64-unknown-linux-pauthtest-clang" Without it Cargo falls back to the system C toolchain (cc) and the compilation fails. +## Controlling pointer authentication features + +Pointer authentication behavior for this target can be configured using the +`-Zpointer-authentication` compiler option. The option accepts a comma-separated +list of values, each of the form `+` - to enable, or `-` - to +disable a feature, where `` is one of: +* `aarch64-jump-table-hardening` - enable hardened lowering for jump-table + dispatch +* `auth-traps` - trap immediately on pointer authentication failure +* `calls` - enable signing and authentication of indirect calls +* `elf-got` - enable authentication of pointers loaded from the ELF GOT +* `function-pointer-type-discrimination` - enable type discrimination for C + function pointers +* `indirect-gotos` - enable signing and authentication of indirect goto targets +* `init-fini` - enable signing of function pointers stored in init/fini arrays +* `init-fini-address-discrimination` - enable address discrimination for + init/fini array entries +* `intrinsics` - enable pointer authentication intrinsics +* `return-addresses` - enable signing and authentication of return addresses +* `typeinfo-vt-ptr-discrimination` - enable type/address discrimination for + authenticated `std::type_info` virtual table pointers +* `vt-ptr-addr-discrimination` - enable address discrimination for authenticated + virtual table pointers +* `vt-ptr-type-discrimination` - enable type discrimination for authenticated + virtual table pointers +For example: +`-Zpointer-authentication=+calls,+return-addresses,-init-fini`. + +Not all options are currently meaningful for Rust code itself. In particular, +the virtual table related ones: `typeinfo-vt-ptr-discrimination`, +`vt-ptr-addr-discrimination`, `vt-ptr-type-discrimination` exist primarily for +interoperability with C++ code and compatibility with the AArch64 Pointer +Authentication ELF ABI. Rust does not implement C++ virtual dispatch semantics, +authenticated C++ member function pointers, or authenticated virtual table +pointers. + +Similarly, `function-pointer-type-discrimination` is recognized for ABI +compatibility purposes, but full support is not yet implemented in Rust. + +Even when these features do not directly affect generated Rust code, they still +contribute to the emitted PAuth ABI metadata through the LLVM module flags: +`aarch64-elf-pauthabi-platform`, `aarch64-elf-pauthabi-version`. These flags are +emitted to communicate pointer authentication ABI requirements to the linker and +other toolchain components. The ABI version value is computed from the enabled +pointer authentication features according to the AArch64 ELF PAuth ABI +specification. The bit layout matches LLVM/Clang definitions. + +### Option semantics and compatibility + +The `-Zpointer-authentication` option is a [target +modifier](https://rust-lang.github.io/rfcs/3716-target-modifiers.html). Target +modifiers are compiler options that affect the ABI, making it unsafe to link +together Rust crates built with different values. The selected pointer +authentication configuration becomes part of a crate's compilation +configuration, and `rustc` verifies that all crates in the dependency graph +agree on its value. If an incompatibility is detected, compilation is rejected +with an ABI mismatch error before invoking the linker, providing a clear +diagnostic. See `tests/ui/target_modifiers/incompatible_pauth.rs` for a sample +use case. + +The order of options is not significant. The compiler canonicalizes the +specified feature set before recording it, so the following are equivalent: + +```text +-Zpointer-authentication=+calls,+init-fini +-Zpointer-authentication=+init-fini,+calls +``` + +If the same option is specified multiple times, the last occurrence takes +precedence, matching Clang's behavior. For example, the following would leave +`init-fini` disable: + +```text +-Zpointer-authentication=+init-fini,-init-fini +``` + ## Cross-compilation toolchains and C code This target supports interoperability with C code. A @@ -391,9 +467,13 @@ The following categories are supported (all present in tree): * End-to-end execution tests * Rust-driven quicksort (pauth-quicksort-rust-driver) * C-driven quicksort (pauth-quicksort-c-driver) -* UI error/warning reporting (the target does not support static linking) +* UI error/warning reporting * crt-static-pauthtest.rs * pauth-static-link-warning + * enable_pointer_authentication_validation.rs + * invalid_target_pointer_authentication.rs + * type_discrimination_not_supported_pointer_authentication.rs + * incompatible_pauth.rs All tests from `assembly-llvm`, `codegen-llvm`, `codegen-units`, `coverage`, `crashes`, `incremental`, `library`, `mir-opt`, `run-make`, `ui` and @@ -407,6 +487,7 @@ x.py test --target aarch64-unknown-linux-pauthtest --force-rerun assembly-llvm \ codegen-llvm codegen-units coverage crashes incremental library mir-opt \ run-make ui ui-fulldeps \ tests/assembly-llvm/pauth-basic.rs \ + tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs \ tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs \ tests/codegen-llvm/pauth/pauth-extern-c.rs \ tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs \ @@ -415,7 +496,11 @@ x.py test --target aarch64-unknown-linux-pauthtest --force-rerun assembly-llvm \ tests/run-make/pauth-quicksort-rust-driver \ tests/run-make/pauth-quicksort-c-driver \ tests/run-make/pauth-static-link-warning \ - tests/ui/statics/crt-static-pauthtest.rs + tests/ui/statics/crt-static-pauthtest.rs \ + tests/ui/pointer_authentication/enable_pointer_authentication_validation.rs \ + tests/ui/pointer_authentication/invalid_target_pointer_authentication.rs \ + tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.rs \ + tests/ui/target_modifiers/incompatible_pauth.rs ``` ## Limitations diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs b/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs index 0e91636416903..e36b516887962 100644 --- a/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs +++ b/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs @@ -1,3 +1,5 @@ +#![allow(invalid_runtime_symbol_definitions)] + fn main() { extern "Rust" { fn malloc(size: usize) -> *mut std::ffi::c_void; diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs index 41aebea2d8add..ecdda9e509d4e 100644 --- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs +++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs @@ -1,3 +1,5 @@ +#![allow(invalid_runtime_symbol_definitions)] + fn main() { extern "C" { fn malloc() -> *mut std::ffi::c_void; diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs index 1f5c509c6666f..1d3fec0fe32f8 100644 --- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs +++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs @@ -1,3 +1,5 @@ +#![allow(invalid_runtime_symbol_definitions)] + fn main() { extern "C" { fn malloc(_: i32, _: i32) -> *mut std::ffi::c_void; diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.rs index dffae7adbb972..6260d55b8f553 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.rs +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.rs @@ -1,3 +1,5 @@ +#![allow(suspicious_runtime_symbol_definitions)] + #[no_mangle] extern "C" fn malloc(_: usize) -> *mut std::ffi::c_void { //~^ HELP: the `malloc` symbol is defined here diff --git a/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs index 77699776aea66..d355da73174e9 100644 --- a/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs @@ -1,5 +1,8 @@ //@ignore-target: windows # File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation + +#![allow(suspicious_runtime_symbol_definitions)] + use std::ffi::{CString, OsStr, c_char, c_int}; use std::os::unix::ffi::OsStrExt; diff --git a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs index b920e6795f90d..ebbf0cc2bf331 100644 --- a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs @@ -1,5 +1,8 @@ //@ignore-target: windows # File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation + +#![allow(invalid_runtime_symbol_definitions)] + use std::ffi::{CString, OsStr, c_char, c_int}; use std::os::unix::ffi::OsStrExt; diff --git a/src/tools/miri/tests/fail/shims/return_type_mismatch.rs b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs index 6dbdd3f539b38..bcde5d8040f59 100644 --- a/src/tools/miri/tests/fail/shims/return_type_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs @@ -1,5 +1,8 @@ //@ignore-target: windows # File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation + +#![allow(suspicious_runtime_symbol_definitions)] + use std::ffi::{CString, OsStr, c_char, c_int, c_short}; use std::os::unix::ffi::OsStrExt; diff --git a/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs index e9cb69418d22f..5453db57bbd8f 100644 --- a/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs +++ b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs @@ -1,5 +1,8 @@ //@ignore-target: windows # File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation + +#![allow(invalid_runtime_symbol_definitions)] + use std::ffi::{CString, OsStr, c_char, c_int}; use std::os::unix::ffi::OsStrExt; diff --git a/tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs b/tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs new file mode 100644 index 0000000000000..04af1b66140dd --- /dev/null +++ b/tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs @@ -0,0 +1,127 @@ +// ignore-tidy-file-linelength +//@ only-pauthtest +//@ revisions: DEFAULT ALL DISABLE_JUMP DISABLE_AUTH_TRAPS DISABLE_CALLS DISABLE_INDIRCT_GOTOS DISABLE_RETURNS DISABLE_INTRINSICS DISABLE_TYPEINFO DISABLE_VT_PTR_ADDR DISABLE_VT_PTR_TYPE NONE + +//@ add-minicore +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![feature(no_core)] + +extern crate minicore; + +//@[DEFAULT] needs-llvm-components: aarch64 +//@[DEFAULT] compile-flags: --target=aarch64-unknown-linux-pauthtest +//@[ALL] needs-llvm-components: aarch64 +//@[ALL] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=+aarch64-jump-table-hardening,+auth-traps,+calls,+indirect-gotos,+return-addresses +//@[DISABLE_JUMP] needs-llvm-components: aarch64 +//@[DISABLE_JUMP] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-aarch64-jump-table-hardening +//@[DISABLE_AUTH_TRAPS] needs-llvm-components: aarch64 +//@[DISABLE_AUTH_TRAPS] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-auth-traps +//@[DISABLE_CALLS] needs-llvm-components: aarch64 +//@[DISABLE_CALLS] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-calls +//@[DISABLE_INDIRCT_GOTOS] needs-llvm-components: aarch64 +//@[DISABLE_INDIRCT_GOTOS] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-indirect-gotos +//@[DISABLE_RETURNS] needs-llvm-components: aarch64 +//@[DISABLE_RETURNS] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-return-addresses +//@[DISABLE_INTRINSICS] needs-llvm-components: aarch64 +//@[DISABLE_INTRINSICS] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-intrinsics +//@[DISABLE_TYPEINFO] needs-llvm-components: aarch64 +//@[DISABLE_TYPEINFO] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-typeinfo-vt-ptr-discrimination +//@[DISABLE_VT_PTR_ADDR] needs-llvm-components: aarch64 +//@[DISABLE_VT_PTR_ADDR] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-vt-ptr-addr-discrimination +//@[DISABLE_VT_PTR_TYPE] needs-llvm-components: aarch64 +//@[DISABLE_VT_PTR_TYPE] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-vt-ptr-type-discrimination +//@[NONE] needs-llvm-components: aarch64 +//@[NONE] compile-flags: --target=aarch64-unknown-linux-pauthtest -Zpointer-authentication=-aarch64-jump-table-hardening,-auth-traps,-calls,-indirect-gotos,-return-addresses,-init-fini,-init-fini-address-discrimination,-intrinsics,-typeinfo-vt-ptr-discrimination,-vt-ptr-addr-discrimination,-vt-ptr-type-discrimination + +// CHECK: define {{.*}} @{{.*}}main{{.*}} [[ATTR_MAIN:#[0-9]+]] +#[inline(never)] +pub fn main() {} +// DEFAULT: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DEFAULT-SAME: "ptrauth-auth-traps" +// DEFAULT-SAME: "ptrauth-calls" +// DEFAULT-SAME: "ptrauth-indirect-gotos" +// DEFAULT-SAME: "ptrauth-returns" +// DEFAULT: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DEFAULT-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1791} + +// DISABLE_JUMP-NOT: aarch64-jump-table-hardening +// DISABLE_JUMP: attributes [[ATTR_MAIN]] = { {{.*}}"ptrauth-auth-traps" +// DISABLE_JUMP-SAME: "ptrauth-calls" +// DISABLE_JUMP-SAME: "ptrauth-indirect-gotos" +// DISABLE_JUMP-SAME: "ptrauth-returns" +// DISABLE_JUMP: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_JUMP-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1791} + +// DISABLE_AUTH_TRAPS-NOT: ptrauth-auth-traps +// DISABLE_AUTH_TRAPS: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_AUTH_TRAPS-SAME: "ptrauth-calls" +// DISABLE_AUTH_TRAPS-SAME: "ptrauth-indirect-gotos" +// DISABLE_AUTH_TRAPS-SAME: "ptrauth-returns" +// DISABLE_AUTH_TRAPS: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_AUTH_TRAPS-NEXT !{i32 1, !"aarch64-elf-pauthabi-version", i32 1783} + +// DISABLE_CALLS-NOT: ptrauth-calls +// DISABLE_CALLS: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_CALLS-SAME: "ptrauth-auth-traps" +// DISABLE_CALLS-SAME: "ptrauth-indirect-gotos" +// DISABLE_CALLS-SAME: "ptrauth-returns" +// DISABLE_CALLS: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_CALLS-SAME-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1789} + +// DISABLE_INDIRCT_GOTOS-NOT: ptrauth-indirect-gotos +// DISABLE_INDIRCT_GOTOS: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_INDIRCT_GOTOS-SAME: "ptrauth-auth-traps" +// DISABLE_INDIRCT_GOTOS-SAME: "ptrauth-calls" +// DISABLE_INDIRCT_GOTOS-SAME: "ptrauth-returns" +// DISABLE_INDIRCT_GOTOS: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1279} +// DISABLE_INDIRCT_GOTOS-NEXT: !{i32 1, !"ptrauth-sign-personality", i32 1} + +// DISABLE_RETURNS-NOT: ptrauth-returns +// DISABLE_RETURNS: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_RETURNS-SAME: "ptrauth-auth-traps" +// DISABLE_RETURNS-SAME: "ptrauth-calls" +// DISABLE_RETURNS-SAME: "ptrauth-indirect-gotos" +// DISABLE_RETURNS: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_RETURNS-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1787} + +// DISABLE_INTRINSICS: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_INTRINSICS-SAME: "ptrauth-auth-traps" +// DISABLE_INTRINSICS-SAME: "ptrauth-calls" +// DISABLE_INTRINSICS-SAME: "ptrauth-indirect-gotos" +// DISABLE_INTRINSICS-SAME: "ptrauth-returns" +// DISABLE_INTRINSICS: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_INTRINSICS-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1790} + +// DISABLE_TYPEINFO: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_TYPEINFO-SAME: "ptrauth-auth-traps" +// DISABLE_TYPEINFO-SAME: "ptrauth-calls" +// DISABLE_TYPEINFO-SAME: "ptrauth-indirect-gotos" +// DISABLE_TYPEINFO-SAME: "ptrauth-returns" +// DISABLE_TYPEINFO: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_TYPEINFO-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 767} + +// DISABLE_VT_PTR_ADDR: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_VT_PTR_ADDR-SAME: "ptrauth-auth-traps" +// DISABLE_VT_PTR_ADDR-SAME: "ptrauth-calls" +// DISABLE_VT_PTR_ADDR-SAME: "ptrauth-indirect-gotos" +// DISABLE_VT_PTR_ADDR-SAME: "ptrauth-returns" +// DISABLE_VT_PTR_ADDR: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_VT_PTR_ADDR-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1775} + +// DISABLE_VT_PTR_TYPE: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" +// DISABLE_VT_PTR_TYPE-SAME: "ptrauth-auth-traps" +// DISABLE_VT_PTR_TYPE-SAME: "ptrauth-calls" +// DISABLE_VT_PTR_TYPE-SAME: "ptrauth-indirect-gotos" +// DISABLE_VT_PTR_TYPE-SAME: "ptrauth-returns" +// DISABLE_VT_PTR_TYPE: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// DISABLE_VT_PTR_TYPE-NEXT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1759} + +// NONE-NOT: ptrauth-returns +// NONE-NOT: aarch64-jump-table-hardening +// NONE-NOT: ptrauth-auth-traps +// NONE-NOT: ptrauth-calls +// NONE-NOT: ptrauth-indirect-gotos +// NONE-NOT: aarch64-elf-pauthabi-platform +// NONE-NOT: aarch64-elf-pauthabi-version diff --git a/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs b/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs index 882cc4c6db971..2751494b9de7a 100644 --- a/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs +++ b/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs @@ -18,10 +18,10 @@ use std::panic; // CHECK-DAG: "ptrauth-returns" // CHECK: attributes [[ATTR_MAIN]] = { {{.*}}"aarch64-jump-table-hardening" -// CHECK-DAG: "ptrauth-auth-traps" -// CHECK-DAG: "ptrauth-calls" -// CHECK-DAG: "ptrauth-indirect-gotos" -// CHECK-DAG: "ptrauth-returns" +// CHECK-SAME: "ptrauth-auth-traps" +// CHECK-SAME: "ptrauth-calls" +// CHECK-SAME: "ptrauth-indirect-gotos" +// CHECK-SAME: "ptrauth-returns" fn main() { let _ = panic::catch_unwind(|| { panic!("BOOM"); diff --git a/tests/codegen-llvm/pauth/pauth-extern-c.rs b/tests/codegen-llvm/pauth/pauth-extern-c.rs index d42dc8d5b4500..b22cf6943a804 100644 --- a/tests/codegen-llvm/pauth/pauth-extern-c.rs +++ b/tests/codegen-llvm/pauth/pauth-extern-c.rs @@ -9,9 +9,9 @@ //@ [O3_PAUTH] needs-llvm-components: aarch64 //@ [O3_PAUTH] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=3 //@ [O0_PAUTH-ELF-GOT] needs-llvm-components: aarch64 -//@ [O0_PAUTH-ELF-GOT] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 -Z ptrauth-elf-got +//@ [O0_PAUTH-ELF-GOT] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 -Z pointer-authentication=+elf-got //@ [O3_PAUTH-ELF-GOT] needs-llvm-components: aarch64 -//@ [O3_PAUTH-ELF-GOT] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=3 -Z ptrauth-elf-got +//@ [O3_PAUTH-ELF-GOT] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=3 -Z pointer-authentication=+elf-got //@ [O0_NO_PAUTH] needs-llvm-components: aarch64 //@ [O0_NO_PAUTH] compile-flags: --target=aarch64-unknown-linux-gnu -C opt-level=0 //@ [O3_NO_PAUTH] needs-llvm-components: aarch64 diff --git a/tests/codegen-llvm/pauth/pauth-init-fini.rs b/tests/codegen-llvm/pauth/pauth-init-fini.rs index db327644d96cf..b54006e56f1f4 100644 --- a/tests/codegen-llvm/pauth/pauth-init-fini.rs +++ b/tests/codegen-llvm/pauth/pauth-init-fini.rs @@ -1,14 +1,23 @@ +// ignore-tidy-file-linelength //@ add-minicore -// ignore-tidy-linelength //@ only-pauthtest -//@ revisions: O0_PAUTH O3_PAUTH +//@ revisions: O0_PAUTH O3_PAUTH O0_PAUTH-ADDR-DISC O3_PAUTH-ADDR-DISC O0_PAUTH-NO-INIT-FINI O3_PAUTH-NO-INIT-FINI //@ [O0_PAUTH] needs-llvm-components: aarch64 //@ [O0_PAUTH] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 +//@ [O0_PAUTH-ADDR-DISC] needs-llvm-components: aarch64 +//@ [O0_PAUTH-ADDR-DISC] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 -Zpointer-authentication=+init-fini-address-discrimination +//@ [O0_PAUTH-NO-INIT-FINI] needs-llvm-components: aarch64 +//@ [O0_PAUTH-NO-INIT-FINI] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 -Zpointer-authentication=-init-fini //@ [O3_PAUTH] needs-llvm-components: aarch64 //@ [O3_PAUTH] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=3 +//@ [O3_PAUTH-ADDR-DISC] needs-llvm-components: aarch64 +//@ [O3_PAUTH-ADDR-DISC] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=3 -Zpointer-authentication=+init-fini-address-discrimination +//@ [O3_PAUTH-NO-INIT-FINI] needs-llvm-components: aarch64 +//@ [O3_PAUTH-NO-INIT-FINI] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 -Zpointer-authentication=-init-fini -// Make sure that init/fini metadata uses correct discriminator: 0xd9d4/55764 +// Make sure that init/fini metadata uses correct discriminator: 0xd9d4/55764 - ptrauth_string_discriminator("init_fini"). +// And that address discriminator can be enabled. #![feature(no_core, lang_items)] #![no_std] @@ -20,12 +29,20 @@ use minicore::*; // O0_PAUTH: @{{[0-9A-Za-z_]+}}GLOBAL_INIT = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}init_fn, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), section ".init_array.90" // O3_PAUTH: @{{[0-9A-Za-z_]+}}GLOBAL_INIT = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}init_fn, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), section ".init_array.90" +// O0_PAUTH-ADDR-DISC: @{{[0-9A-Za-z_]+}}GLOBAL_INIT = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}init_fn, i32 0, i64 55764, ptr @_RNvCsf7kshQi9mOB_15pauth_init_fini7init_fn), section ".init_array.90" +// O3_PAUTH-ADDR-DISC: @{{[0-9A-Za-z_]+}}GLOBAL_INIT = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}init_fn, i32 0, i64 55764, ptr @_RNvCsf7kshQi9mOB_15pauth_init_fini7init_fn), section ".init_array.90" +// O0_PAUTH-NO-INIT-FINI-NOT: @{{[0-9A-Za-z_]+}}GLOBAL_INIT = constant ptr ptrauth +// O0_PAUTH-NO-INIT-FINI-ADDR-DISC: @{{[0-9A-Za-z_]+}}GLOBAL_INIT = constant ptr ptrauth #[used] #[link_section = ".init_array.90"] static GLOBAL_INIT: extern "C" fn() = init_fn; // O0_PAUTH: @{{[0-9A-Za-z_]+}}GLOBAL_FINI = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}fini_fn, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), section ".fini_array.90" // O3_PAUTH: @{{[0-9A-Za-z_]+}}GLOBAL_FINI = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}fini_fn, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), section ".fini_array.90" +// O0_PAUTH-ADDR-DISC: @{{[0-9A-Za-z_]+}}GLOBAL_FINI = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}fini_fn, i32 0, i64 55764, ptr @_RNvCsf7kshQi9mOB_15pauth_init_fini7fini_fn), section ".fini_array.90" +// O3_PAUTH-ADDR-DISC: @{{[0-9A-Za-z_]+}}GLOBAL_FINI = constant ptr ptrauth (ptr @{{[0-9A-Za-z_]+}}fini_fn, i32 0, i64 55764, ptr @_RNvCsf7kshQi9mOB_15pauth_init_fini7fini_fn), section ".fini_array.90" +// O0_PAUTH-NO-INIT-FINI-NOT: @{{[0-9A-Za-z_]+}}GLOBAL_FINI = constant ptr ptrauth +// O3_PAUTH-NO-INIT-FINI-NOT: @{{[0-9A-Za-z_]+}}GLOBAL_FINI = constant ptr ptrauth #[used] #[link_section = ".fini_array.90"] static GLOBAL_FINI: extern "C" fn(i32) = fini_fn; diff --git a/tests/ui/README.md b/tests/ui/README.md index 85a5e6e0cbe1c..0a7dd5c2cd033 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1083,6 +1083,10 @@ See [Tracking issue for pin ergonomics #130494](https://github.com/rust-lang/rus See [`std::pin`](https://doc.rust-lang.org/std/pin/). +## `tests/ui/pointer_authentication/` + +Tests for `-Zpointer-authentication` compiler flag. + ## `tests/ui/precondition-checks/` Exercises on some unsafe precondition checks. diff --git a/tests/ui/abi/stack-protector.rs b/tests/ui/abi/stack-protector.rs index dd0d0d43182ea..6a2b0d0854c4a 100644 --- a/tests/ui/abi/stack-protector.rs +++ b/tests/ui/abi/stack-protector.rs @@ -9,6 +9,7 @@ #![allow(function_casts_as_integer)] use std::env; +use std::ffi::c_void; use std::process::{Command, ExitStatus}; fn main() { @@ -42,7 +43,9 @@ fn vulnerable_function() { let bad_code_ptr = malicious_code as usize; // Overwrite the on-stack return address with the address of `malicious_code()`, // thereby jumping to that function when returning from `vulnerable_function()`. - unsafe { fill(stackaddr, bad_code_ptr, 20); } + unsafe { + fill(stackaddr, bad_code_ptr, 20); + } // Capture the address, so the write is not optimized away. std::hint::black_box(stackaddr); } @@ -68,16 +71,15 @@ unsafe fn fill(addr: *mut usize, val: usize, count: usize) { fn malicious_code() { let msg = [112u8, 119u8, 110u8, 101u8, 100u8, 33u8, 0u8]; // "pwned!\0" ascii unsafe { - write(1, &msg as *const u8, msg.len()); + write(1, &msg as *const u8 as *const c_void, msg.len()); _exit(0); } } extern "C" { - fn write(fd: i32, buf: *const u8, count: usize) -> isize; + fn write(fd: i32, buf: *const c_void, count: usize) -> isize; fn _exit(status: i32) -> !; } - fn assert_stack_smash_prevented(cmd: &mut Command) { let (status, stdout, stderr) = run(cmd); assert!(!status.success()); @@ -92,7 +94,6 @@ fn assert_stack_smashed(cmd: &mut Command) { assert!(stderr.is_empty()); } - fn run(cmd: &mut Command) -> (ExitStatus, String, String) { let output = cmd.output().unwrap(); let stdout = String::from_utf8_lossy(&output.stdout); diff --git a/tests/ui/cfg/conditional-compile.rs b/tests/ui/cfg/conditional-compile.rs index 637bd0e12e8be..3cdd1d52f8881 100644 --- a/tests/ui/cfg/conditional-compile.rs +++ b/tests/ui/cfg/conditional-compile.rs @@ -47,7 +47,7 @@ struct r { #[cfg(false)] fn r(i: isize) -> r { - r { i: i } + r { i } } struct r { @@ -55,7 +55,7 @@ struct r { } fn r(i: isize) -> r { - r { i: i } + r { i } } #[cfg(false)] @@ -111,8 +111,8 @@ mod test_foreign_items { pub mod rustrt { extern "C" { #[cfg(false)] - pub fn write() -> String; - pub fn write() -> String; + pub fn foo() -> String; + pub fn foo() -> String; } } } diff --git a/tests/ui/codegen/trait-objects-slice-coercion.rs b/tests/ui/codegen/trait-objects-slice-coercion.rs new file mode 100644 index 0000000000000..59282e3616b7d --- /dev/null +++ b/tests/ui/codegen/trait-objects-slice-coercion.rs @@ -0,0 +1,12 @@ +//! Regression test for . +//! This used to trigger LLVM assertion +//! `SrcTy must be larger than DestTy for Trunc` +//! because of a redundant truncate call when value is boolean. +//@ run-pass + +trait Tc {} +impl Tc for bool {} + +fn main() { + let _: &[&dyn Tc] = &[&true]; +} diff --git a/tests/ui/issues/issue-41298.rs b/tests/ui/coherence/inherent-impls-with-same-fn-ptr-return.rs similarity index 54% rename from tests/ui/issues/issue-41298.rs rename to tests/ui/coherence/inherent-impls-with-same-fn-ptr-return.rs index 6008110712348..9c6c5a3178961 100644 --- a/tests/ui/issues/issue-41298.rs +++ b/tests/ui/coherence/inherent-impls-with-same-fn-ptr-return.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! Two impl blocks with same generics caused ICE during coherence overlap +//! check. //@ check-pass + #![allow(dead_code)] struct Function { t: T, f: F } diff --git a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.expr.stderr b/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.expr.stderr new file mode 100644 index 0000000000000..016c7afc4b8b5 --- /dev/null +++ b/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.expr.stderr @@ -0,0 +1,13 @@ +error: expected expression, found `direct_const_arg!()` constant + --> $DIR/invalid-direct-const-arg-owner-issue-159172.rs:21:13 + | +LL | let _ = core::direct_const_arg!(|| { + | _____________^ +LL | | +LL | | use std::io::*; +LL | | write!(_, "") +LL | | }); + | |______^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.rs b/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.rs new file mode 100644 index 0000000000000..80673ec127adf --- /dev/null +++ b/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.rs @@ -0,0 +1,26 @@ +//@ revisions: ty expr +#![feature(min_generic_const_args)] + +#[cfg(ty)] +trait Iter< + const C: core::direct_const_arg!(|| { + //[ty]~^ ERROR expected type, found `direct_const_arg!()` constant + use std::io::*; + let mut buffer = std::fs::File::create("foo.txt")?; + write!(buffer, "oh no")?; + }), +> +{ +} + +#[cfg(ty)] +fn main() {} + +#[cfg(expr)] +fn main() { + let _ = core::direct_const_arg!(|| { + //[expr]~^ ERROR expected expression, found `direct_const_arg!()` constant + use std::io::*; + write!(_, "") + }); +} diff --git a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.ty.stderr b/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.ty.stderr new file mode 100644 index 0000000000000..936153ce52b75 --- /dev/null +++ b/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.ty.stderr @@ -0,0 +1,14 @@ +error: expected type, found `direct_const_arg!()` constant + --> $DIR/invalid-direct-const-arg-owner-issue-159172.rs:6:14 + | +LL | const C: core::direct_const_arg!(|| { + | ______________^ +LL | | +LL | | use std::io::*; +LL | | let mut buffer = std::fs::File::create("foo.txt")?; +LL | | write!(buffer, "oh no")?; +LL | | }), + | |______^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/issues/issue-41849-variance-req.rs b/tests/ui/consts/const-eval/variance-const-eval-cycle.rs similarity index 70% rename from tests/ui/issues/issue-41849-variance-req.rs rename to tests/ui/consts/const-eval/variance-const-eval-cycle.rs index 1da844ab4bf0b..03251f38126ee 100644 --- a/tests/ui/issues/issue-41849-variance-req.rs +++ b/tests/ui/consts/const-eval/variance-const-eval-cycle.rs @@ -1,6 +1,9 @@ +//! Regression test for . +//! Evaluating const required to evaluate trait, which required variance +//! information, which required const to be evaluated. //@ run-pass + #![allow(dead_code)] -// Regression test for #41849. use std::ops::Mul; diff --git a/tests/ui/extern/extern-pub.rs b/tests/ui/extern/extern-pub.rs index b272bc5359fd0..9e91ca7f3324f 100644 --- a/tests/ui/extern/extern-pub.rs +++ b/tests/ui/extern/extern-pub.rs @@ -1,7 +1,7 @@ //@ run-pass extern "C" { - pub fn free(p: *const u8); + pub fn free(p: *mut std::ffi::c_void); } pub fn main() {} diff --git a/tests/ui/ffi/ffi-struct-size-alignment.rs b/tests/ui/ffi/ffi-struct-size-alignment.rs index 15ad3232555bb..287ae7cad2b6d 100644 --- a/tests/ui/ffi/ffi-struct-size-alignment.rs +++ b/tests/ui/ffi/ffi-struct-size-alignment.rs @@ -5,7 +5,6 @@ // Incorrect struct size computation in the FFI, because of not taking // the alignment of elements into account. - use std::ffi::{c_uint, c_void}; pub struct KEYGEN { @@ -17,7 +16,7 @@ pub struct KEYGEN { extern "C" { // Bogus signature, just need to test if it compiles. - pub fn malloc(data: KEYGEN); + pub fn foo(data: KEYGEN); } pub fn main() {} diff --git a/tests/ui/issues/issue-41742.rs b/tests/ui/indexing/index-with-wrong-type.rs similarity index 74% rename from tests/ui/issues/issue-41742.rs rename to tests/ui/indexing/index-with-wrong-type.rs index afe311b4d1785..c783287ac4273 100644 --- a/tests/ui/issues/issue-41742.rs +++ b/tests/ui/indexing/index-with-wrong-type.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test indexing with the wrong type doesn't cause ICE. + use std::ops::{Index, IndexMut}; struct S; diff --git a/tests/ui/issues/issue-41742.stderr b/tests/ui/indexing/index-with-wrong-type.stderr similarity index 83% rename from tests/ui/issues/issue-41742.stderr rename to tests/ui/indexing/index-with-wrong-type.stderr index 47c7e5dc11ff7..d1196b2d3b522 100644 --- a/tests/ui/issues/issue-41742.stderr +++ b/tests/ui/indexing/index-with-wrong-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-41742.rs:24:7 + --> $DIR/index-with-wrong-type.rs:27:7 | LL | H["?"].f(); | ^^^ expected `u32`, found `&str` diff --git a/tests/ui/issues/issue-41677.rs b/tests/ui/inference/bivariant-param.rs similarity index 59% rename from tests/ui/issues/issue-41677.rs rename to tests/ui/inference/bivariant-param.rs index 211d1176363f5..b63dd19e577ad 100644 --- a/tests/ui/issues/issue-41677.rs +++ b/tests/ui/inference/bivariant-param.rs @@ -1,8 +1,8 @@ +//! Regression test for . +//! The local variable was winding up with a type `Receiver` where +//! `?T` was unconstrained, because we failed to enforce the WF obligations +//! and `?T` is a bivariant type parameter position. //@ run-pass -// Regression test for #41677. The local variable was winding up with -// a type `Receiver` where `?T` was unconstrained, because we -// failed to enforce the WF obligations and `?T` is a bivariant type -// parameter position. #![allow(unused_variables, dead_code)] diff --git a/tests/ui/inference/infer-result-type-through-dead-code.rs b/tests/ui/inference/infer-result-type-through-dead-code.rs new file mode 100644 index 0000000000000..b4497f8d8bc49 --- /dev/null +++ b/tests/ui/inference/infer-result-type-through-dead-code.rs @@ -0,0 +1,14 @@ +//! Regression test for . +//! The key here is that the error type of the `Ok` call ought to be +//! constrained to `String`, even though it is dead-code. +//@ check-pass + +#![allow(dead_code)] +#![allow(unreachable_code)] + +fn main() {} + +fn t() -> Result<(), String> { + return Err("".into()); + Ok(()) +} diff --git a/tests/ui/issues/issue-39984.rs b/tests/ui/issues/issue-39984.rs deleted file mode 100644 index eff5d69bf84b1..0000000000000 --- a/tests/ui/issues/issue-39984.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ check-pass -#![allow(dead_code)] -#![allow(unreachable_code)] -// Regression test for issue #39984. -// -// The key here is that the error type of the `Ok` call ought to be -// constrained to `String`, even though it is dead-code. - -fn main() {} - -fn t() -> Result<(), String> { - return Err("".into()); - Ok(()) -} diff --git a/tests/ui/issues/issue-41479.rs b/tests/ui/issues/issue-41479.rs deleted file mode 100644 index c8ebad6c5e071..0000000000000 --- a/tests/ui/issues/issue-41479.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass -fn split(pair: (A, B)) { - let _a = pair.0; - let _b = pair.1; -} - -fn main() { - split(((), ((), ()))); -} diff --git a/tests/ui/issues/issue-41744.rs b/tests/ui/issues/issue-41744.rs deleted file mode 100644 index af360d9580771..0000000000000 --- a/tests/ui/issues/issue-41744.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -trait Tc {} -impl Tc for bool {} - -fn main() { - let _: &[&dyn Tc] = &[&true]; -} diff --git a/tests/ui/issues/issue-4025.rs b/tests/ui/lifetimes/if-else-branches-lifetime-coercion.rs similarity index 78% rename from tests/ui/issues/issue-4025.rs rename to tests/ui/lifetimes/if-else-branches-lifetime-coercion.rs index c75421fb82f15..c740291b50f3b 100644 --- a/tests/ui/issues/issue-4025.rs +++ b/tests/ui/lifetimes/if-else-branches-lifetime-coercion.rs @@ -1,9 +1,9 @@ +//! Regression test for . +//! `if` expression requires both paths to have a common supertype. //@ check-pass + #![allow(dead_code)] #![allow(unused_mut)] -/* -# if b { x } else { y } requires identical types for x and y -*/ fn print1(b: bool, s1: &str, s2: &str) { println!("{}", if b { s1 } else { s2 }); diff --git a/tests/ui/issues/issue-40288-2.rs b/tests/ui/lifetimes/lifetime-errors/mut-slice-struct-lifetime-transmute.rs similarity index 80% rename from tests/ui/issues/issue-40288-2.rs rename to tests/ui/lifetimes/lifetime-errors/mut-slice-struct-lifetime-transmute.rs index 032a2e65ff07e..270dc989ff538 100644 --- a/tests/ui/issues/issue-40288-2.rs +++ b/tests/ui/lifetimes/lifetime-errors/mut-slice-struct-lifetime-transmute.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! We were subtyping in the wrong direction, allowing any lifetime to +//! become 'static, which made use-after-free possible. + fn prove_static(_: &'static T) {} fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { diff --git a/tests/ui/issues/issue-40288-2.stderr b/tests/ui/lifetimes/lifetime-errors/mut-slice-struct-lifetime-transmute.stderr similarity index 87% rename from tests/ui/issues/issue-40288-2.stderr rename to tests/ui/lifetimes/lifetime-errors/mut-slice-struct-lifetime-transmute.stderr index 81cb7cdd51ff6..d65ca848f7ae9 100644 --- a/tests/ui/issues/issue-40288-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/mut-slice-struct-lifetime-transmute.stderr @@ -1,5 +1,5 @@ error[E0621]: explicit lifetime required in the type of `y` - --> $DIR/issue-40288-2.rs:9:5 + --> $DIR/mut-slice-struct-lifetime-transmute.rs:13:5 | LL | out[0] | ^^^^^^ lifetime `'a` required @@ -10,7 +10,7 @@ LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &'a T) -> &'a T { | ++ error[E0621]: explicit lifetime required in the type of `y` - --> $DIR/issue-40288-2.rs:24:5 + --> $DIR/mut-slice-struct-lifetime-transmute.rs:28:5 | LL | out.head | ^^^^^^^^ lifetime `'a` required diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.rs b/tests/ui/lint/dead-code/lint-dead-code-3.rs index 20b568054dfb7..7e733fc11c1db 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-3.rs +++ b/tests/ui/lint/dead-code/lint-dead-code-3.rs @@ -48,24 +48,28 @@ mod blah { enum c_void {} extern "C" { - fn free(p: *const c_void); - fn malloc(size: usize) -> *const c_void; + fn my_free(p: *const c_void); + fn my_malloc(size: usize) -> *const c_void; } pub fn baz() { - unsafe { free(malloc(4)); } + unsafe { + my_free(my_malloc(4)); + } } } enum c_void {} //~ ERROR: enum `c_void` is never used extern "C" { - fn free(p: *const c_void); //~ ERROR: function `free` is never used + fn my_free(p: *const c_void); //~ ERROR: function `my_free` is never used } // Check provided method mod inner { pub trait Trait { - fn f(&self) { f(); } + fn f(&self) { + f(); + } } impl Trait for isize {} diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.stderr b/tests/ui/lint/dead-code/lint-dead-code-3.stderr index 5c68cf0e18b67..acc5de4a93786 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/tests/ui/lint/dead-code/lint-dead-code-3.stderr @@ -25,28 +25,28 @@ LL | fn bar() { | ^^^ error: enum `c_void` is never used - --> $DIR/lint-dead-code-3.rs:60:6 + --> $DIR/lint-dead-code-3.rs:62:6 | LL | enum c_void {} | ^^^^^^ error: function `blah` is never used - --> $DIR/lint-dead-code-3.rs:77:8 + --> $DIR/lint-dead-code-3.rs:81:8 | LL | fn blah() {} | ^^^^ error: function `blah` is never used - --> $DIR/lint-dead-code-3.rs:81:12 + --> $DIR/lint-dead-code-3.rs:85:12 | LL | fn blah() {} | ^^^^ -error: function `free` is never used - --> $DIR/lint-dead-code-3.rs:62:8 +error: function `my_free` is never used + --> $DIR/lint-dead-code-3.rs:64:8 | -LL | fn free(p: *const c_void); - | ^^^^ +LL | fn my_free(p: *const c_void); + | ^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/lint/runtime-symbols-no-std.rs b/tests/ui/lint/runtime-symbols-no-std.rs new file mode 100644 index 0000000000000..cef75e45b02d3 --- /dev/null +++ b/tests/ui/lint/runtime-symbols-no-std.rs @@ -0,0 +1,27 @@ +// This test makes sure that the following symbols are not linted against +// in a #[no_std] context. + +//@ check-pass + +#![no_std] +#![crate_type = "lib"] + +use core::ffi::{c_char, c_int, c_void}; + +#[no_mangle] +pub fn open() {} + +extern "C" { + pub fn read(); + pub fn write(); +} + +#[no_mangle] +pub static close: () = (); + +extern "C" { + pub fn malloc(); + pub fn realloc(); + pub fn free(); + pub fn exit(); +} diff --git a/tests/ui/lint/runtime-symbols-unix.rs b/tests/ui/lint/runtime-symbols-unix.rs new file mode 100644 index 0000000000000..517cf765195f3 --- /dev/null +++ b/tests/ui/lint/runtime-symbols-unix.rs @@ -0,0 +1,57 @@ +// This test checks the runtime symbols lint with the Unix symbols. + +//@ only-unix +//@ edition: 2021 +//@ normalize-stderr: "\*const [iu]8" -> "*const U8" + +#![feature(c_variadic)] +#![allow(clashing_extern_declarations)] // we are voluntarily testing different definitions + +use core::ffi::{c_char, c_int, c_void}; + +fn invalid() { + #[no_mangle] + pub fn open() {} + //~^ ERROR invalid definition of the runtime `open` symbol + + extern "C" { + pub fn read(); + //~^ ERROR invalid definition of the runtime `read` symbol + + pub fn write(); + //~^ ERROR invalid definition of the runtime `write` symbol + } + + #[no_mangle] + pub static close: () = (); + //~^ ERROR invalid definition of the runtime `close` symbol + + extern "C" { + pub fn malloc(); + //~^ ERROR invalid definition of the runtime `malloc` symbol + + pub fn realloc(); + //~^ ERROR invalid definition of the runtime `realloc` symbol + + pub fn free(); + //~^ ERROR invalid definition of the runtime `free` symbol + + pub fn exit(); + //~^ ERROR invalid definition of the runtime `exit` symbol + } +} + +fn suspicious() { + extern "C" { + pub fn open(path: *const u8, oflag: usize, ...) -> c_int; + //~^ WARN suspicious definition of the runtime `open` symbol + + pub fn free(ptr: *const u8); + //~^ WARN suspicious definition of the runtime `free` symbol + + pub fn exit(code: f32) -> !; + //~^ WARN suspicious definition of the runtime `exit` symbol + } +} + +fn main() {} diff --git a/tests/ui/lint/runtime-symbols-unix.stderr b/tests/ui/lint/runtime-symbols-unix.stderr new file mode 100644 index 0000000000000..7ef765c29684d --- /dev/null +++ b/tests/ui/lint/runtime-symbols-unix.stderr @@ -0,0 +1,117 @@ +error: invalid definition of the runtime `open` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:14:5 + | +LL | pub fn open() {} + | ^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(*const U8, i32, ...) -> i32` + found `fn()` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "open")]`, or `#[link_name = "open"]` + = note: `#[deny(invalid_runtime_symbol_definitions)]` on by default + +error: invalid definition of the runtime `read` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:18:9 + | +LL | pub fn read(); + | ^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(i32, *mut c_void, usize) -> isize` + found `unsafe extern "C" fn()` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "read")]`, or `#[link_name = "read"]` + +error: invalid definition of the runtime `write` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:21:9 + | +LL | pub fn write(); + | ^^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(i32, *const c_void, usize) -> isize` + found `unsafe extern "C" fn()` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "write")]`, or `#[link_name = "write"]` + +error: invalid definition of the runtime `close` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:26:5 + | +LL | pub static close: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(i32) -> i32` + found `static close: ()` + = help: either fix the signature or remove any attributes `#[unsafe(no_mangle)]` or `#[unsafe(export_name = "close")]` + +error: invalid definition of the runtime `malloc` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:30:9 + | +LL | pub fn malloc(); + | ^^^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(usize) -> *mut c_void` + found `unsafe extern "C" fn()` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "malloc")]`, or `#[link_name = "malloc"]` + +error: invalid definition of the runtime `realloc` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:33:9 + | +LL | pub fn realloc(); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void` + found `unsafe extern "C" fn()` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "realloc")]`, or `#[link_name = "realloc"]` + +error: invalid definition of the runtime `free` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:36:9 + | +LL | pub fn free(); + | ^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(*mut c_void)` + found `unsafe extern "C" fn()` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "free")]`, or `#[link_name = "free"]` + +error: invalid definition of the runtime `exit` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:39:9 + | +LL | pub fn exit(); + | ^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(i32) -> !` + found `unsafe extern "C" fn()` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "exit")]`, or `#[link_name = "exit"]` + +warning: suspicious definition of the runtime `open` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:46:9 + | +LL | pub fn open(path: *const U8, oflag: usize, ...) -> c_int; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(*const U8, i32, ...) -> i32` + found `unsafe extern "C" fn(*const U8, usize, ...) -> i32` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "open")]`, or `#[link_name = "open"]` + = help: allow this lint if the signature is compatible + = note: `#[warn(suspicious_runtime_symbol_definitions)]` on by default + +warning: suspicious definition of the runtime `free` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:49:9 + | +LL | pub fn free(ptr: *const U8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(*mut c_void)` + found `unsafe extern "C" fn(*const U8)` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "free")]`, or `#[link_name = "free"]` + = help: allow this lint if the signature is compatible + +warning: suspicious definition of the runtime `exit` symbol used by the standard library + --> $DIR/runtime-symbols-unix.rs:52:9 + | +LL | pub fn exit(code: f32) -> !; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected `unsafe extern "C" fn(i32) -> !` + found `unsafe extern "C" fn(f32) -> !` + = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "exit")]`, or `#[link_name = "exit"]` + = help: allow this lint if the signature is compatible + +error: aborting due to 8 previous errors; 3 warnings emitted + diff --git a/tests/ui/lint/warn-ctypes-inhibit.rs b/tests/ui/lint/warn-ctypes-inhibit.rs index 0f401150adf64..1de661a6994e6 100644 --- a/tests/ui/lint/warn-ctypes-inhibit.rs +++ b/tests/ui/lint/warn-ctypes-inhibit.rs @@ -1,9 +1,9 @@ //@ run-pass - -#![allow(dead_code)] //@ compile-flags:-D improper-ctypes +#![allow(dead_code)] #![allow(improper_ctypes)] +#![allow(suspicious_runtime_symbol_definitions)] mod libc { extern "C" { diff --git a/tests/ui/pointer_authentication/enable_pointer_authentication_validation.all_unknown.stderr b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.all_unknown.stderr new file mode 100644 index 0000000000000..47e61f2b8be73 --- /dev/null +++ b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.all_unknown.stderr @@ -0,0 +1,2 @@ +error: incorrect value `+I,+do,-not,-exist` for unstable option `pointer-authentication` - a comma-separated list of options, each of the form `+` or `-`, where `` is one of: `aarch64-jump-table-hardening`, `auth-traps`, `calls`, `elf-got`, `function-pointer-type-discrimination`, `indirect-gotos`, `init-fini`, `init-fini-address-discrimination`, `intrinsics`, `return-addresses`, `typeinfo-vt-ptr-discrimination`, `vt-ptr-addr-discrimination` or `vt-ptr-type-discrimination` was expected + diff --git a/tests/ui/pointer_authentication/enable_pointer_authentication_validation.empty.stderr b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.empty.stderr new file mode 100644 index 0000000000000..9a4cd16c15a14 --- /dev/null +++ b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.empty.stderr @@ -0,0 +1,2 @@ +error: incorrect value `` for unstable option `pointer-authentication` - a comma-separated list of options, each of the form `+` or `-`, where `` is one of: `aarch64-jump-table-hardening`, `auth-traps`, `calls`, `elf-got`, `function-pointer-type-discrimination`, `indirect-gotos`, `init-fini`, `init-fini-address-discrimination`, `intrinsics`, `return-addresses`, `typeinfo-vt-ptr-discrimination`, `vt-ptr-addr-discrimination` or `vt-ptr-type-discrimination` was expected + diff --git a/tests/ui/pointer_authentication/enable_pointer_authentication_validation.mixed.stderr b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.mixed.stderr new file mode 100644 index 0000000000000..ea8b9250f31b9 --- /dev/null +++ b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.mixed.stderr @@ -0,0 +1,2 @@ +error: incorrect value `+elf-got,-imaginary` for unstable option `pointer-authentication` - a comma-separated list of options, each of the form `+` or `-`, where `` is one of: `aarch64-jump-table-hardening`, `auth-traps`, `calls`, `elf-got`, `function-pointer-type-discrimination`, `indirect-gotos`, `init-fini`, `init-fini-address-discrimination`, `intrinsics`, `return-addresses`, `typeinfo-vt-ptr-discrimination`, `vt-ptr-addr-discrimination` or `vt-ptr-type-discrimination` was expected + diff --git a/tests/ui/pointer_authentication/enable_pointer_authentication_validation.rs b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.rs new file mode 100644 index 0000000000000..d7306508f39d4 --- /dev/null +++ b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.rs @@ -0,0 +1,24 @@ +//@ ignore-backends: gcc +//@ revisions: empty unprefixed all_unknown all_known mixed + +//@[empty] needs-llvm-components: aarch64 +//@[empty] compile-flags: --target aarch64-unknown-linux-pauthtest -Zpointer-authentication= +//@[unprefixed] needs-llvm-components: aarch64 +//@[unprefixed] compile-flags: --target aarch64-unknown-linux-pauthtest -Zpointer-authentication=auth-traps +//@[all_unknown] needs-llvm-components: aarch64 +//@[all_unknown] compile-flags: --target aarch64-unknown-linux-pauthtest -Zpointer-authentication=+I,+do,-not,-exist +//@[all_known] check-pass +//@[all_known] needs-llvm-components: aarch64 +//@[all_known] compile-flags: --target aarch64-unknown-linux-pauthtest -Zpointer-authentication=+elf-got,-init-fini +//@[mixed] needs-llvm-components: aarch64 +//@[mixed] compile-flags: --target aarch64-unknown-linux-pauthtest -Zpointer-authentication=+elf-got,-imaginary + +#![feature(no_core)] +#![no_std] +#![no_main] +#![no_core] + +//[empty]~? ERROR incorrect value `` for unstable option `pointer-authentication` +//[unprefixed]~? ERROR incorrect value `auth-traps` for unstable option `pointer-authentication` +//[all_unknown]~? ERROR incorrect value `+I,+do,-not,-exist` for unstable option `pointer-authentication` +//[mixed]~? ERROR incorrect value `+elf-got,-imaginary` for unstable option `pointer-authentication` diff --git a/tests/ui/pointer_authentication/enable_pointer_authentication_validation.unprefixed.stderr b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.unprefixed.stderr new file mode 100644 index 0000000000000..c6ff1e36350ee --- /dev/null +++ b/tests/ui/pointer_authentication/enable_pointer_authentication_validation.unprefixed.stderr @@ -0,0 +1,2 @@ +error: incorrect value `auth-traps` for unstable option `pointer-authentication` - a comma-separated list of options, each of the form `+` or `-`, where `` is one of: `aarch64-jump-table-hardening`, `auth-traps`, `calls`, `elf-got`, `function-pointer-type-discrimination`, `indirect-gotos`, `init-fini`, `init-fini-address-discrimination`, `intrinsics`, `return-addresses`, `typeinfo-vt-ptr-discrimination`, `vt-ptr-addr-discrimination` or `vt-ptr-type-discrimination` was expected + diff --git a/tests/ui/pointer_authentication/invalid_target_pointer_authentication.rs b/tests/ui/pointer_authentication/invalid_target_pointer_authentication.rs new file mode 100644 index 0000000000000..2d8b3b7a1915d --- /dev/null +++ b/tests/ui/pointer_authentication/invalid_target_pointer_authentication.rs @@ -0,0 +1,11 @@ +//@ ignore-backends: gcc +//@ check-pass +//@ needs-llvm-components: aarch64 + +//@ compile-flags: -Zpointer-authentication=-elf-got --crate-type=lib --target aarch64-unknown-linux-gnu + +#![feature(no_core)] +#![no_std] +#![no_main] +#![no_core] +//~? WARN `-Z pointer-authentication` is not supported for target aarch64-unknown-linux-gnu and will be ignored diff --git a/tests/ui/pointer_authentication/invalid_target_pointer_authentication.stderr b/tests/ui/pointer_authentication/invalid_target_pointer_authentication.stderr new file mode 100644 index 0000000000000..1b1a33fd16c2b --- /dev/null +++ b/tests/ui/pointer_authentication/invalid_target_pointer_authentication.stderr @@ -0,0 +1,4 @@ +warning: `-Z pointer-authentication` is not supported for target aarch64-unknown-linux-gnu and will be ignored + +warning: 1 warning emitted + diff --git a/tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.rs b/tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.rs new file mode 100644 index 0000000000000..6838e749fd333 --- /dev/null +++ b/tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.rs @@ -0,0 +1,12 @@ +//@ ignore-backends: gcc +//@ check-fail +//@ needs-llvm-components: aarch64 + +//@ compile-flags: -Zpointer-authentication=+function-pointer-type-discrimination --crate-type=lib --target aarch64-unknown-linux-pauthtest + +#![feature(no_core)] +#![no_std] +#![no_main] +#![no_core] + +//~? ERROR function pointer type discrimination is not supported diff --git a/tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.stderr b/tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.stderr new file mode 100644 index 0000000000000..c040b0cb61f66 --- /dev/null +++ b/tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.stderr @@ -0,0 +1,4 @@ +error: function pointer type discrimination is not supported + +error: aborting due to 1 previous error + diff --git a/tests/ui/privacy/pub-extern-privacy.rs b/tests/ui/privacy/pub-extern-privacy.rs index 0f9131685b0e2..e01d86acf6547 100644 --- a/tests/ui/privacy/pub-extern-privacy.rs +++ b/tests/ui/privacy/pub-extern-privacy.rs @@ -1,11 +1,10 @@ //@ run-pass - use std::mem::transmute; mod a { extern "C" { - pub fn free(x: *const u8); + pub fn free(x: *mut std::ffi::c_void); } } diff --git a/tests/ui/target_modifiers/auxiliary/pauth.rs b/tests/ui/target_modifiers/auxiliary/pauth.rs new file mode 100644 index 0000000000000..761f4a520a4d2 --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/pauth.rs @@ -0,0 +1,7 @@ +//@ compile-flags: --target aarch64-unknown-linux-pauthtest -Zpointer-authentication=+calls,+init-fini +//@ needs-llvm-components: aarch64 +//@ only-pauthtest + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/incompatible_pauth.error_generated.stderr b/tests/ui/target_modifiers/incompatible_pauth.error_generated.stderr new file mode 100644 index 0000000000000..ddc05e4b55322 --- /dev/null +++ b/tests/ui/target_modifiers/incompatible_pauth.error_generated.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zpointer-authentication` will cause an ABI mismatch in crate `incompatible_pauth` + --> $DIR/incompatible_pauth.rs:14:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zpointer-authentication` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: `-Zpointer-authentication=+calls,-init-fini` in this crate is incompatible with `-Zpointer-authentication=+calls,+init-fini` in dependency `pauth` + = help: set `-Zpointer-authentication=+calls,+init-fini` in this crate or `-Zpointer-authentication=+calls,-init-fini` in `pauth` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=pointer-authentication` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/incompatible_pauth.rs b/tests/ui/target_modifiers/incompatible_pauth.rs new file mode 100644 index 0000000000000..6fe77a6916568 --- /dev/null +++ b/tests/ui/target_modifiers/incompatible_pauth.rs @@ -0,0 +1,20 @@ +//@ aux-build:pauth.rs +//@ revisions: ok ok_reverse_order ok_last_one_wins error_generated +//@ compile-flags: --target=aarch64-unknown-linux-pauthtest +//@ [ok] compile-flags: -Zpointer-authentication=+calls,+init-fini +//@ [ok] check-pass +//@ [ok_last_one_wins] compile-flags: -Zpointer-authentication=-calls,+calls,-init-fini,+init-fini +//@ [ok_last_one_wins] check-pass +//@ [ok_reverse_order] compile-flags: -Zpointer-authentication=+init-fini,+calls +//@ [ok_reverse_order] check-pass +//@ [error_generated] compile-flags: -Zpointer-authentication=+calls,-init-fini +//@ needs-llvm-components: aarch64 +//@ only-pauthtest + +#![feature(no_core)] +//[error_generated]~^ ERROR mixing `-Zpointer-authentication` will cause an ABI mismatch in crate +//`incompatible_pauth` +#![crate_type = "rlib"] +#![no_core] + +extern crate pauth; diff --git a/tests/ui/tuple/nested-zst-tuple-fields.rs b/tests/ui/tuple/nested-zst-tuple-fields.rs new file mode 100644 index 0000000000000..f160f25a5eeac --- /dev/null +++ b/tests/ui/tuple/nested-zst-tuple-fields.rs @@ -0,0 +1,12 @@ +//! Regression test for . +//! Field access on zst tuple items used to trigger LLVM assertion. +//@ run-pass + +fn split(pair: (A, B)) { + let _a = pair.0; + let _b = pair.1; +} + +fn main() { + split(((), ((), ()))); +} diff --git a/tests/ui/issues/issue-41604.rs b/tests/ui/typeck/method-call-on-computed-array-index.rs similarity index 54% rename from tests/ui/issues/issue-41604.rs rename to tests/ui/typeck/method-call-on-computed-array-index.rs index 3cd16a2a598ba..928be8c31efdd 100644 --- a/tests/ui/issues/issue-41604.rs +++ b/tests/ui/typeck/method-call-on-computed-array-index.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This used to ICE. //@ run-pass + struct B; impl B {