From 9c411ab2f213e9d4bd68dc1dfab6a27ed7d79dbb Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 8 Sep 2025 16:47:37 +0000 Subject: [PATCH 1/9] Stabilize `-Zstack-protector` as `-Cstack-protector` I propose stabilizing `-Cstack-protector` as `-Zstack-protector`. This PR adds a new `-Cstack-protector` flag, leaving the unstable `-Z` flag as is to ease the transition period. The `-Z` flag will be removed in the future. No RFC/MCP, this flag was added in 84197 and was not deemed large enough to require additional process. The tracking issue for this feature is 114903. The `-Cstack-protector=strong` mode uses the same underlying heuristics as Clang's `-fstack-protector-strong`. These heuristics weren't designed for Rust, and may be over-conservative in some cases - for example, if Rust stores a field's data in an alloca using an LLVM array type, LLVM regard the alloca as meaning that the function has a C array, and enable stack overflow canaries even if the function accesses the alloca in a safe way. Some people thought we should wait on stabilization until there are better heuristics, but I didn't hear about any concrete case where this unduly harms performance, and I think that when a need comes, we can improve the heuristics in LLVM after stabilization. The heuristics do seem to not be under-conservative, so this should not be a security risk. The `-Cstack-protector=basic` mode (`-fstack-protector`) uses heuristics that are specifically designed to catch old-C-style string manipulation. This is not a good fit to Rust, which does not perform much unsafe C-style string manipulation. As far as I can tell, nobody has been asking for it, and few people are using it even in today's C - modern distros (e.g. [Debian]) tend to use `-fstack-protector-strong`. Therefore, `-Cstack-protector=basic` has been **removed**. If anyone is interested in it, they are welcome to add it back as an unstable option. [Debian]: https://wiki.debian.org/Hardening#DEB_BUILD_HARDENING_STACKPROTECTOR_.28gcc.2Fg.2B-.2B-_-fstack-protector-strong.29 Most implementation was done in . The command-line attribute enables the relevant LLVM attribute on all functions in . Each target can indicate that it does not support stack canaries - currently, the GPU platforms `nvptx64-nvidia-cuda` and `amdgcn-amd-amdhsa`. On these platforms, use of `-Cstack-protector` causes an error. The feature has tests that make sure that the LLVM heuristic gives reasonable results for several functions, by checking for `__security_check_cookie` (on Windows) or `__stack_chk_fail` (on Linux). See No call-for-testing has been conducted, but the feature seems to be in use. No reported bugs seem to exist. - bbjornse was the original implementor at 84197 - mrcnski documented it at 111722 - wesleywiser added tests for Windows at 116037 - davidtwco worked on the feature at 121742 - nikic provided support from the LLVM side (on Zulip on and elsewhere), thanks nikic! No FIXMEs related to this feature. This feature cannot cause undefined behavior. No changes to reference/spec, docs added to the codegen docs as part of the stabilization PR. No. None. No support needed for rustdoc, clippy, rust-analyzer, rustfmt or rustup. Cargo could expose this as an option in build profiles but I would expect the decision as to what version should be used would be made for the entire crate graph at build time rather than by individual package authors. `-C stack-protector` is propagated to C compilers using cc-rs via rust-lang/cc-rs issue 1550 --- bootstrap.example.toml | 2 +- compiler/rustc_codegen_llvm/src/lib.rs | 29 ++++++++++----- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/messages.ftl | 2 +- compiler/rustc_session/src/options.rs | 12 +++++-- compiler/rustc_session/src/session.rs | 17 ++++----- src/bootstrap/src/core/builder/cargo.rs | 2 +- src/doc/rustc/src/codegen-options/index.md | 28 +++++++++++++++ src/doc/rustc/src/exploit-mitigations.md | 2 +- ...otector-heuristics-effect-windows-32bit.rs | 8 ++--- ...otector-heuristics-effect-windows-64bit.rs | 8 ++--- .../stack-protector-heuristics-effect.rs | 8 ++--- .../stack-protector-target-support.rs | 12 +++---- tests/codegen-llvm/stack-protector.rs | 36 ++++++++++++++++--- tests/ui/README.md | 2 +- tests/ui/abi/stack-protector.rs | 2 +- ...l-stack-protector-unsupported.all-z.stderr | 4 +++ ...ail-stack-protector-unsupported.all.stderr | 4 +++ .../fail-stack-protector-unsupported.rs | 30 ++++++++++++++++ ...-stack-protector-unsupported.strong.stderr | 4 +++ ...arn-stack-protector-unsupported.all.stderr | 4 --- ...n-stack-protector-unsupported.basic.stderr | 4 --- ...-stack-protector-unsupported.strong.stderr | 4 --- 23 files changed, 164 insertions(+), 62 deletions(-) create mode 100644 tests/ui/stack-protector/fail-stack-protector-unsupported.all-z.stderr create mode 100644 tests/ui/stack-protector/fail-stack-protector-unsupported.all.stderr create mode 100644 tests/ui/stack-protector/fail-stack-protector-unsupported.rs create mode 100644 tests/ui/stack-protector/fail-stack-protector-unsupported.strong.stderr delete mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr delete mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr delete mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr diff --git a/bootstrap.example.toml b/bootstrap.example.toml index e0cbb0c0e747c..85bc7d56b4bd9 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -755,7 +755,7 @@ #rust.frame-pointers = false # Indicates whether stack protectors should be used -# via the unstable option `-Zstack-protector`. +# via `-Cstack-protector`. # # Valid options are : `none`(default),`basic`,`strong`, or `all`. # `strong` and `basic` options may be buggy and are not recommended, see rust-lang/rust#114903. diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 438a74e0a0912..0a2106e81167e 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -300,19 +300,32 @@ impl CodegenBackend for LlvmCodegenBackend { Generate stack canaries in all functions. strong - Generate stack canaries in a function if it either: - - has a local variable of `[T; N]` type, regardless of `T` and `N` - - takes the address of a local variable. + Generate stack canaries for all functions, unless the compiler + can prove these functions can't be the source of a stack + buffer overflow (even in the presence of undefined behavior). - (Note that a local variable being borrowed is not equivalent to its - address being taken: e.g. some borrows may be removed by optimization, - while by-value argument passing may be implemented with reference to a - local stack variable in the ABI.) + This provides the same security guarantees as Clang's + `-fstack-protector=strong`. + + The exact rules are unstable and subject to change, but + currently, it generates stack protectors for functions that, + *post-optimization*, contain either arrays (of any size + or type) or address-taken locals. basic - Generate stack canaries in functions with local variables of `[T; N]` + Generate stack canaries in functions that are heuristically + suspected to contain buffer overflows. + + The heuristic is subject to change, but currently it + includes functions with local variables of `[T; N]` type, where `T` is byte-sized and `N` >= 8. + This heuristic originated from C, where it detects + functions that allocate a `char buf[N];` buffer on the + stack, and are therefore likely to have a stack buffer overflow + in the case of a length-calculation error. It is *not* a good + heuristic for Rust code. + none Do not generate stack canaries. "# diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index d075f94ef8502..0f0fc989e0356 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -641,6 +641,7 @@ fn test_codegen_options_tracking_hash() { tracked!(relro_level, Some(RelroLevel::Full)); tracked!(soft_float, true); tracked!(split_debuginfo, Some(SplitDebuginfo::Packed)); + tracked!(stack_protector, StackProtector::All); tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(target_cpu, Some(String::from("abc"))); tracked!(target_feature, String::from("all the features, all of them")); @@ -871,7 +872,6 @@ fn test_unstable_options_tracking_hash() { tracked!(small_data_threshold, Some(16)); tracked!(split_lto_unit, Some(true)); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); - tracked!(stack_protector, StackProtector::All); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(tiny_const_eval_limit, true); diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index eff55e8e02a2e..7c5122c47cbad 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -130,7 +130,7 @@ session_target_requires_unwind_tables = target requires unwind tables, they cann session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored -session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored +session_target_stack_protector_not_supported = `-C stack-protector={$stack_protector}` is not supported for target {$target_triple} session_unexpected_builtin_cfg = unexpected `--cfg {$cfg}` flag .controlled_by = config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}` diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 21fa3321a30ad..cd367fcb1fc12 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1917,9 +1917,12 @@ pub mod parse { true } - pub(crate) fn parse_stack_protector(slot: &mut StackProtector, v: Option<&str>) -> bool { + pub(crate) fn parse_stack_protector( + slot: &mut Option, + v: Option<&str>, + ) -> bool { match v.and_then(|s| StackProtector::from_str(s).ok()) { - Some(ssp) => *slot = ssp, + Some(ssp) => *slot = Some(ssp), _ => return false, } true @@ -2211,6 +2214,9 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::split_debuginfo` instead of this field")] split_debuginfo: Option = (None, parse_split_debuginfo, [TRACKED], "how to handle split-debuginfo, a platform-specific option"), + #[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")] + stack_protector: Option = (None, parse_stack_protector, [TRACKED], + "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), symbol_mangling_version: Option = (None, @@ -2687,7 +2693,7 @@ written to standard error output)"), src_hash_algorithm: Option = (None, parse_src_file_hash, [TRACKED], "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), #[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")] - stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED], + stack_protector: Option = (None, parse_stack_protector, [TRACKED], "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED], "allow staticlibs to have rust dylib dependencies"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1a0ec600af47d..cdd7184f778d2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -714,11 +714,12 @@ impl Session { } pub fn stack_protector(&self) -> StackProtector { - if self.target.options.supports_stack_protector { - self.opts.unstable_opts.stack_protector - } else { - StackProtector::None - } + // -C stack-protector overwrites -Z stack-protector, default to StackProtector::None + self.opts + .cg + .stack_protector + .or(self.opts.unstable_opts.stack_protector) + .unwrap_or(StackProtector::None) } pub fn must_emit_unwind_tables(&self) -> bool { @@ -1240,10 +1241,10 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } - if sess.opts.unstable_opts.stack_protector != StackProtector::None { + if sess.stack_protector() != StackProtector::None { if !sess.target.options.supports_stack_protector { - sess.dcx().emit_warn(errors::StackProtectorNotSupportedForTarget { - stack_protector: sess.opts.unstable_opts.stack_protector, + sess.dcx().emit_err(errors::StackProtectorNotSupportedForTarget { + stack_protector: sess.stack_protector(), target_triple: &sess.opts.target_triple, }); } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index b95533e112029..b52cf14bb5513 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -952,7 +952,7 @@ impl Builder<'_> { cargo.env(profile_var("STRIP"), self.config.rust_strip.to_string()); if let Some(stack_protector) = &self.config.rust_stack_protector { - rustflags.arg(&format!("-Zstack-protector={stack_protector}")); + rustflags.arg(&format!("-Cstack-protector={stack_protector}")); } let debuginfo_level = match mode { diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index f0f991ed0c909..57bd3f3e0b316 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -695,6 +695,34 @@ Note that all three options are supported on Linux and Apple platforms, Attempting to use an unsupported option requires using the nightly channel with the `-Z unstable-options` flag. +## stack-protector + +The option `-C stack-protector` (currently also supported in the +old style `-Z stack-protector`) controls the generation of +stack-protector canaries. + +This flag controls stack smashing protection strategy. + +Supported values for this option are: +- `none` (default): Disable stack canary generation +- `basic`: Generate stack canaries in functions that are suspected + to have a high chance of containing stack buffer overflows (deprecated). +- `strong`: Generate stack canaries in all functions, unless the compiler + can prove these functions can't be the source of a stack + buffer overflow (even in the presence of undefined behavior). + + This provides the same security guarantees as Clang's + `-fstack-protector=strong`. + + The exact rules are unstable and subject to change, but + currently, it generates stack protectors for functions that, + *post-optimization*, contain either arrays (of any size + or type) or address-taken locals. +- `all`: Generate stack canaries in all functions + +Stack protectors are not supported on many GPU targets, use of stack +protectors on these targets is an error. + ## strip The option `-C strip=val` controls stripping of debuginfo and similar auxiliary diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index 41e5c93a1b7dc..2523cdeb3b099 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -62,7 +62,7 @@ equivalent. | Stack clashing protection | Yes | Yes | 1.20.0 (2017-08-31) | | Read-only relocations and immediate binding | Yes | Yes | 1.21.0 (2017-10-12) | | Heap corruption protection | Yes | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) | -| Stack smashing protection | Yes | No, `-Z stack-protector` | Nightly | +| Stack smashing protection | Yes | No, `-C stack-protector` | ??? | | Forward-edge control flow protection | Yes | No, `-Z sanitizer=cfi` | Nightly | | Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | No, `-Z sanitizer=shadow-call-stack,safestack` | Nightly | diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index d1b51068fce5a..c6b54cf7c3c70 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -3,10 +3,10 @@ //@ only-windows //@ only-msvc //@ ignore-64bit 64-bit table based SEH has slightly different behaviors than classic SEH -//@ [all] compile-flags: -Z stack-protector=all -//@ [strong] compile-flags: -Z stack-protector=strong -//@ [basic] compile-flags: -Z stack-protector=basic -//@ [none] compile-flags: -Z stack-protector=none +//@ [all] compile-flags: -C stack-protector=all +//@ [strong] compile-flags: -C stack-protector=strong +//@ [basic] compile-flags: -C stack-protector=basic +//@ [none] compile-flags: -C stack-protector=none //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort -Cdebuginfo=1 #![crate_type = "lib"] diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index 56a6f08da5877..c5304b35e8e55 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -3,10 +3,10 @@ //@ only-windows //@ only-msvc //@ ignore-32bit 64-bit table based SEH has slightly different behaviors than classic SEH -//@ [all] compile-flags: -Z stack-protector=all -//@ [strong] compile-flags: -Z stack-protector=strong -//@ [basic] compile-flags: -Z stack-protector=basic -//@ [none] compile-flags: -Z stack-protector=none +//@ [all] compile-flags: -C stack-protector=all +//@ [strong] compile-flags: -C stack-protector=strong +//@ [basic] compile-flags: -C stack-protector=basic +//@ [none] compile-flags: -C stack-protector=none //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort #![crate_type = "lib"] diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs index 3728ff3adf105..31a31a807a613 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs @@ -4,10 +4,10 @@ //@ ignore-msvc stack check code uses different function names //@ ignore-nvptx64 stack protector is not supported //@ ignore-wasm32-unknown-unknown -//@ [all] compile-flags: -Z stack-protector=all -//@ [strong] compile-flags: -Z stack-protector=strong -//@ [basic] compile-flags: -Z stack-protector=basic -//@ [none] compile-flags: -Z stack-protector=none +//@ [all] compile-flags: -C stack-protector=all +//@ [strong] compile-flags: -C stack-protector=strong +//@ [basic] compile-flags: -C stack-protector=basic +//@ [none] compile-flags: -C stack-protector=none //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled // NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR, diff --git a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs index 9f182985d1573..c29f06cce16b8 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs @@ -4,7 +4,7 @@ //@ add-minicore //@ revisions: r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 //@ revisions: r24 r25 r26 r27 r28 r29 r30 r31 r32 r33 r36 r37 r38 r39 r40 r41 r42 r43 r44 -//@ revisions: r45 r46 r47 r48 r49 r50 r51 r52 r53 r54 r55 r56 r57 r58 r59 r60 r61 r62 r63 r64 r65 +//@ revisions: r45 r46 r47 r48 r50 r51 r52 r53 r54 r55 r56 r57 r58 r59 r60 r61 r62 r63 r64 r65 //@ revisions: r66 r67 r68 r69 r70 r71 r72 r73 r74 r75 r76 r77 r78 r79 r80 r81 r82 r83 r84 r85 //@ assembly-output: emit-asm //@ [r1] compile-flags: --target aarch64-unknown-linux-gnu @@ -99,8 +99,8 @@ //@ [r47] needs-llvm-components: mips //@ [r48] compile-flags: --target mipsel-unknown-linux-musl //@ [r48] needs-llvm-components: mips -//@ [r49] compile-flags: --target nvptx64-nvidia-cuda -//@ [r49] needs-llvm-components: nvptx +//-@ [r49] compile-flags: --target nvptx64-nvidia-cuda [stack protector not supported on CUDA +//- see the test fail-stack-protector-unsupported] //@ [r50] compile-flags: --target powerpc-unknown-linux-gnu //@ [r50] needs-llvm-components: powerpc //@ [r51] compile-flags: --target powerpc64-unknown-linux-gnu @@ -173,7 +173,7 @@ //@ [r84] needs-llvm-components: x86 //@ [r85] compile-flags: --target x86_64-unknown-redox //@ [r85] needs-llvm-components: x86 -//@ compile-flags: -Z stack-protector=all -Cpanic=abort +//@ compile-flags: -C stack-protector=all -Cpanic=abort //@ compile-flags: -C opt-level=2 #![crate_type = "lib"] @@ -193,10 +193,6 @@ pub fn foo() { // r7: callq __security_check_cookie // r13: bl __security_check_cookie - // cuda doesn't support stack-smash protection - // r49-NOT: __security_check_cookie - // r49-NOT: __stack_chk_fail - // Other targets do stack checking within the function, and call a failure function on error // r1: __stack_chk_fail // r2: __stack_chk_fail diff --git a/tests/codegen-llvm/stack-protector.rs b/tests/codegen-llvm/stack-protector.rs index 8ab25b470cda1..686db3f1f4412 100644 --- a/tests/codegen-llvm/stack-protector.rs +++ b/tests/codegen-llvm/stack-protector.rs @@ -1,8 +1,12 @@ -//@ revisions: all strong basic none +//@ revisions: all all-z strong strong-z basic basic-z none strong-c-overrides-z //@ ignore-nvptx64 stack protector not supported -//@ [all] compile-flags: -Z stack-protector=all -//@ [strong] compile-flags: -Z stack-protector=strong -//@ [basic] compile-flags: -Z stack-protector=basic +//@ [all] compile-flags: -C stack-protector=all +//@ [all-z] compile-flags: -Z stack-protector=all +//@ [strong] compile-flags: -C stack-protector=strong +//@ [strong-z] compile-flags: -Z stack-protector=strong +//@ [basic] compile-flags: -C stack-protector=basic +//@ [basic-z] compile-flags: -Z stack-protector=basic +//@ [strong-c-overrides-z] compile-flags: -C stack-protector=strong -Z stack-protector=all #![crate_type = "lib"] @@ -16,18 +20,42 @@ pub fn foo() { // all-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } // all-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // all-z-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // all-z-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // all-z: attributes #0 = { {{.*}}sspreq {{.*}} } + // all-z-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // all-z-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} } // strong: attributes #0 = { {{.*}}sspstrong {{.*}} } // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // strong-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // strong-z-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // strong-z: attributes #0 = { {{.*}}sspstrong {{.*}} } + // strong-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // strong-z-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + + // strong-c-overrides-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // strong-c-overrides-z-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // strong-c-overrides-z: attributes #0 = { {{.*}}sspstrong {{.*}} } + // strong-c-overrides-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // strong-c-overrides-z-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } // basic: attributes #0 = { {{.*}}ssp {{.*}} } // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // basic-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // basic-z-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // basic-z: attributes #0 = { {{.*}}ssp {{.*}} } + // basic-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // basic-z-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // none-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } // none-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } // none-NOT: attributes #0 = { {{.*}}ssp {{.*}} } diff --git a/tests/ui/README.md b/tests/ui/README.md index 4c91f313a7351..60b2224b65985 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1229,7 +1229,7 @@ Stability attributes used internally by the standard library: `#[stable()]` and Some tests for pretty printing of rustc_public's IR. -## `tests/ui/stack-protector/`: `-Z stack-protector` command line flag +## `tests/ui/stack-protector/`: `-C stack-protector` command line flag See [Tracking Issue for stabilizing stack smashing protection (i.e., `-Z stack-protector`) #114903](https://github.com/rust-lang/rust/issues/114903). diff --git a/tests/ui/abi/stack-protector.rs b/tests/ui/abi/stack-protector.rs index dd0d0d43182ea..3c52d9ff1ae4d 100644 --- a/tests/ui/abi/stack-protector.rs +++ b/tests/ui/abi/stack-protector.rs @@ -1,7 +1,7 @@ //@ run-pass //@ only-x86_64-unknown-linux-gnu //@ revisions: ssp no-ssp -//@ [ssp] compile-flags: -Z stack-protector=all +//@ [ssp] compile-flags: -C stack-protector=all //@ compile-flags: -C opt-level=2 //@ compile-flags: -g //@ ignore-backends: gcc diff --git a/tests/ui/stack-protector/fail-stack-protector-unsupported.all-z.stderr b/tests/ui/stack-protector/fail-stack-protector-unsupported.all-z.stderr new file mode 100644 index 0000000000000..9f2876de057fd --- /dev/null +++ b/tests/ui/stack-protector/fail-stack-protector-unsupported.all-z.stderr @@ -0,0 +1,4 @@ +error: `-C stack-protector=all` is not supported for target nvptx64-nvidia-cuda + +error: aborting due to 1 previous error + diff --git a/tests/ui/stack-protector/fail-stack-protector-unsupported.all.stderr b/tests/ui/stack-protector/fail-stack-protector-unsupported.all.stderr new file mode 100644 index 0000000000000..9f2876de057fd --- /dev/null +++ b/tests/ui/stack-protector/fail-stack-protector-unsupported.all.stderr @@ -0,0 +1,4 @@ +error: `-C stack-protector=all` is not supported for target nvptx64-nvidia-cuda + +error: aborting due to 1 previous error + diff --git a/tests/ui/stack-protector/fail-stack-protector-unsupported.rs b/tests/ui/stack-protector/fail-stack-protector-unsupported.rs new file mode 100644 index 0000000000000..c9eb3560eda42 --- /dev/null +++ b/tests/ui/stack-protector/fail-stack-protector-unsupported.rs @@ -0,0 +1,30 @@ +//@ check-fail +//@ revisions: all strong all-z +//@ compile-flags: --target nvptx64-nvidia-cuda +//@ needs-llvm-components: nvptx +//@ [all] compile-flags: -C stack-protector=all +//@ [strong] compile-flags: -C stack-protector=strong +//@ [all-z] compile-flags: -Z stack-protector=all + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +trait Sized: MetaSized {} + +#[lang = "copy"] +trait Copy {} + +pub fn main(){} + +//[all]~? ERROR `-C stack-protector=all` is not supported for target nvptx64-nvidia-cuda +//[all-z]~? ERROR `-C stack-protector=all` is not supported for target nvptx64-nvidia-cuda +//[strong]~? ERROR `-C stack-protector=strong` is not supported for target nvptx64-nvidia-cuda diff --git a/tests/ui/stack-protector/fail-stack-protector-unsupported.strong.stderr b/tests/ui/stack-protector/fail-stack-protector-unsupported.strong.stderr new file mode 100644 index 0000000000000..a92575e597af8 --- /dev/null +++ b/tests/ui/stack-protector/fail-stack-protector-unsupported.strong.stderr @@ -0,0 +1,4 @@ +error: `-C stack-protector=strong` is not supported for target nvptx64-nvidia-cuda + +error: aborting due to 1 previous error + diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr b/tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr deleted file mode 100644 index 54887715523c1..0000000000000 --- a/tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored - -warning: 1 warning emitted - diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr b/tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr deleted file mode 100644 index f7a1ee39fb9af..0000000000000 --- a/tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored - -warning: 1 warning emitted - diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr b/tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr deleted file mode 100644 index ccc2f9f2cc5b8..0000000000000 --- a/tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored - -warning: 1 warning emitted - From 1e99ab6cfb46bda808cc64af78f0982ba142377a Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 9 Sep 2025 11:26:18 +0000 Subject: [PATCH 2/9] remove stack-protector=basic stack-protector=basic is a heuristic designed for C putting this in its own commit to allow for easy reversion if someone wants it --- bootstrap.example.toml | 3 +-- compiler/rustc_codegen_llvm/src/attributes.rs | 1 - compiler/rustc_codegen_llvm/src/lib.rs | 14 ----------- compiler/rustc_interface/src/tests.rs | 3 ++- compiler/rustc_target/src/spec/mod.rs | 6 ----- src/doc/rustc/src/codegen-options/index.md | 2 -- ...otector-heuristics-effect-windows-32bit.rs | 25 +++++-------------- ...otector-heuristics-effect-windows-64bit.rs | 25 +++++-------------- .../stack-protector-heuristics-effect.rs | 21 +++------------- tests/codegen-llvm/stack-protector.rs | 14 ----------- .../no-stack-protector-basic.rs | 9 +++++++ .../no-stack-protector-basic.stable.stderr | 2 ++ .../no-stack-protector-basic.unstable.stderr | 2 ++ 13 files changed, 32 insertions(+), 95 deletions(-) create mode 100644 tests/ui/stack-protector/no-stack-protector-basic.rs create mode 100644 tests/ui/stack-protector/no-stack-protector-basic.stable.stderr create mode 100644 tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 85bc7d56b4bd9..7342daa4e36ca 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -757,8 +757,7 @@ # Indicates whether stack protectors should be used # via `-Cstack-protector`. # -# Valid options are : `none`(default),`basic`,`strong`, or `all`. -# `strong` and `basic` options may be buggy and are not recommended, see rust-lang/rust#114903. +# Valid options are : `none`(default), `strong`, or `all`. #rust.stack-protector = "none" # Prints each test name as it is executed, to help debug issues in the test harness itself. diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index a25ce9e5a90ac..9a8ae738e15a0 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -294,7 +294,6 @@ fn stackprotector_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll A StackProtector::None => return None, StackProtector::All => AttributeKind::StackProtectReq, StackProtector::Strong => AttributeKind::StackProtectStrong, - StackProtector::Basic => AttributeKind::StackProtect, }; Some(sspattr.create_attr(cx.llcx)) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 0a2106e81167e..8e00581f65bae 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -312,20 +312,6 @@ impl CodegenBackend for LlvmCodegenBackend { *post-optimization*, contain either arrays (of any size or type) or address-taken locals. - basic - Generate stack canaries in functions that are heuristically - suspected to contain buffer overflows. - - The heuristic is subject to change, but currently it - includes functions with local variables of `[T; N]` - type, where `T` is byte-sized and `N` >= 8. - - This heuristic originated from C, where it detects - functions that allocate a `char buf[N];` buffer on the - stack, and are therefore likely to have a stack buffer overflow - in the case of a length-calculation error. It is *not* a good - heuristic for Rust code. - none Do not generate stack canaries. "# diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0f0fc989e0356..323458d22bbb0 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -641,7 +641,7 @@ fn test_codegen_options_tracking_hash() { tracked!(relro_level, Some(RelroLevel::Full)); tracked!(soft_float, true); tracked!(split_debuginfo, Some(SplitDebuginfo::Packed)); - tracked!(stack_protector, StackProtector::All); + tracked!(stack_protector, Some(StackProtector::All)); tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(target_cpu, Some(String::from("abc"))); tracked!(target_feature, String::from("all the features, all of them")); @@ -872,6 +872,7 @@ fn test_unstable_options_tracking_hash() { tracked!(small_data_threshold, Some(16)); tracked!(split_lto_unit, Some(true)); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); + tracked!(stack_protector, Some(StackProtector::All)); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(tiny_const_eval_limit, true); diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 89c9fdc935cc5..af27cc005f4da 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1340,12 +1340,6 @@ crate::target_spec_enum! { /// Disable stack canary generation. None = "none", - /// On LLVM, mark all generated LLVM functions with the `ssp` attribute (see - /// llvm/docs/LangRef.rst). This triggers stack canary generation in - /// functions which contain an array of a byte-sized type with more than - /// eight elements. - Basic = "basic", - /// On LLVM, mark all generated LLVM functions with the `sspstrong` /// attribute (see llvm/docs/LangRef.rst). This triggers stack canary /// generation in functions which either contain an array, or which take diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 57bd3f3e0b316..9924e35941e55 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -705,8 +705,6 @@ This flag controls stack smashing protection strategy. Supported values for this option are: - `none` (default): Disable stack canary generation -- `basic`: Generate stack canaries in functions that are suspected - to have a high chance of containing stack buffer overflows (deprecated). - `strong`: Generate stack canaries in all functions, unless the compiler can prove these functions can't be the source of a stack buffer overflow (even in the presence of undefined behavior). diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index c6b54cf7c3c70..493ed78ace15a 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -1,11 +1,10 @@ -//@ revisions: all strong basic none missing +//@ revisions: all strong none missing //@ assembly-output: emit-asm //@ only-windows //@ only-msvc //@ ignore-64bit 64-bit table based SEH has slightly different behaviors than classic SEH //@ [all] compile-flags: -C stack-protector=all //@ [strong] compile-flags: -C stack-protector=strong -//@ [basic] compile-flags: -C stack-protector=basic //@ [none] compile-flags: -C stack-protector=none //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort -Cdebuginfo=1 @@ -18,7 +17,6 @@ pub fn emptyfn() { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } @@ -36,7 +34,6 @@ pub fn array_char(f: fn(*const char)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -54,7 +51,6 @@ pub fn array_u8_1(f: fn(*const u8)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -70,10 +66,10 @@ pub fn array_u8_small(f: fn(*const u8)) { f(&b as *const _); // Small arrays do not lead to stack protection by the 'basic' heuristic. + // (basic is not currently supported, leaving the test anyway). // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -88,10 +84,10 @@ pub fn array_u8_large(f: fn(*const u8)) { // Since `a` is a byte array with size greater than 8, the basic heuristic // will also protect this function. + // (basic is not currently supported, leaving the test anyway). // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -109,10 +105,10 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { // Since `a` is a byte array in the LLVM output, the basic heuristic will // also protect this function. + // (basic is not currently supported, leaving the test anyway). // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -138,10 +134,10 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // } // EOF // ``` + // (basic is not currently supported, leaving the test anyway). // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -159,7 +155,6 @@ pub fn local_string_addr_taken(f: fn(&String)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -190,7 +185,6 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -229,7 +223,6 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -260,7 +253,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -302,7 +294,6 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -316,7 +307,6 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -330,7 +320,6 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -352,12 +341,10 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // function and into `f()`, this is implemented with pass-by-reference // using a suitably constructed fat-pointer (as if the functions // accepted &[u8]). This function therefore doesn't need dynamic array - // alloca, and is therefore not protected by the `strong` or `basic` - // heuristics. + // alloca, and is therefore not protected by the `strong` heuristic. // all-NOT: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index c5304b35e8e55..ce186c69432e6 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -1,11 +1,10 @@ -//@ revisions: all strong basic none missing +//@ revisions: all strong none missing //@ assembly-output: emit-asm //@ only-windows //@ only-msvc //@ ignore-32bit 64-bit table based SEH has slightly different behaviors than classic SEH //@ [all] compile-flags: -C stack-protector=all //@ [strong] compile-flags: -C stack-protector=strong -//@ [basic] compile-flags: -C stack-protector=basic //@ [none] compile-flags: -C stack-protector=none //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort @@ -17,7 +16,6 @@ pub fn emptyfn() { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } @@ -36,7 +34,6 @@ pub fn array_char(f: fn(*const char)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -55,7 +52,6 @@ pub fn array_u8_1(f: fn(*const u8)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -72,10 +68,10 @@ pub fn array_u8_small(f: fn(*const u8)) { f(&b as *const _); // Small arrays do not lead to stack protection by the 'basic' heuristic. + // (basic is not currently supported, leaving the test anyway). // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -91,10 +87,10 @@ pub fn array_u8_large(f: fn(*const u8)) { // Since `a` is a byte array with size greater than 8, the basic heuristic // will also protect this function. + // (basic is not currently supported, leaving the test anyway). // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -113,10 +109,10 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { // Since `a` is a byte array in the LLVM output, the basic heuristic will // also protect this function. + // (basic is not currently supported, leaving the test anyway). // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -146,7 +142,6 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -165,7 +160,6 @@ pub fn local_string_addr_taken(f: fn(&String)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -197,7 +191,6 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -237,7 +230,6 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -269,7 +261,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -312,7 +303,6 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -327,7 +317,6 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -342,7 +331,6 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // all: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie @@ -365,12 +353,11 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // function and into `f()`, this is implemented with pass-by-reference // using a suitably constructed fat-pointer (as if the functions // accepted &[u8]). This function therefore doesn't need dynamic array - // alloca, and is therefore not protected by the `strong` or `basic` - // heuristics. + // alloca, and is therefore not protected by the `strong` heuristic. // all-NOT: __security_check_cookie // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie + // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs index 31a31a807a613..4b78a643b7b7b 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs @@ -1,4 +1,4 @@ -//@ revisions: all strong basic none missing +//@ revisions: all strong none missing //@ assembly-output: emit-asm //@ ignore-apple slightly different policy on stack protection of arrays //@ ignore-msvc stack check code uses different function names @@ -6,7 +6,6 @@ //@ ignore-wasm32-unknown-unknown //@ [all] compile-flags: -C stack-protector=all //@ [strong] compile-flags: -C stack-protector=strong -//@ [basic] compile-flags: -C stack-protector=basic //@ [none] compile-flags: -C stack-protector=none //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled @@ -24,7 +23,6 @@ pub fn emptyfn() { // all: __stack_chk_fail // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -42,7 +40,6 @@ pub fn array_char(f: fn(*const char)) { // all: __stack_chk_fail // strong: __stack_chk_fail - // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -58,7 +55,6 @@ pub fn array_u8_1(f: fn(*const u8)) { // all: __stack_chk_fail // strong: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -72,10 +68,10 @@ pub fn array_u8_small(f: fn(*const u8)) { f(&b as *const _); // Small arrays do not lead to stack protection by the 'basic' heuristic. + // (basic is not currently supported, leaving the test anyway). // all: __stack_chk_fail // strong: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -88,10 +84,10 @@ pub fn array_u8_large(f: fn(*const u8)) { // Since `a` is a byte array with size greater than 8, the basic heuristic // will also protect this function. + // (basic is not currently supported, leaving the test anyway). // all: __stack_chk_fail // strong: __stack_chk_fail - // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -107,10 +103,10 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { // Since `a` is a byte array in the LLVM output, the basic heuristic will // also protect this function. + // (basic is not currently supported, leaving the test anyway). // all: __stack_chk_fail // strong: __stack_chk_fail - // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -137,7 +133,6 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // all: __stack_chk_fail // strong: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -153,7 +148,6 @@ pub fn local_string_addr_taken(f: fn(&String)) { // all: __stack_chk_fail // strong: __stack_chk_fail - // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -182,7 +176,6 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // all: __stack_chk_fail // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -219,7 +212,6 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // all: __stack_chk_fail // strong: __stack_chk_fail - // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -248,7 +240,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // all: __stack_chk_fail // strong: __stack_chk_fail - // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -288,7 +279,6 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { // all: __stack_chk_fail // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -300,7 +290,6 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // all: __stack_chk_fail // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -312,7 +301,6 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // all: __stack_chk_fail // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -339,7 +327,6 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // all: __stack_chk_fail // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } diff --git a/tests/codegen-llvm/stack-protector.rs b/tests/codegen-llvm/stack-protector.rs index 686db3f1f4412..1477d2ed7b28a 100644 --- a/tests/codegen-llvm/stack-protector.rs +++ b/tests/codegen-llvm/stack-protector.rs @@ -4,8 +4,6 @@ //@ [all-z] compile-flags: -Z stack-protector=all //@ [strong] compile-flags: -C stack-protector=strong //@ [strong-z] compile-flags: -Z stack-protector=strong -//@ [basic] compile-flags: -C stack-protector=basic -//@ [basic-z] compile-flags: -Z stack-protector=basic //@ [strong-c-overrides-z] compile-flags: -C stack-protector=strong -Z stack-protector=all #![crate_type = "lib"] @@ -44,18 +42,6 @@ pub fn foo() { // strong-c-overrides-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } // strong-c-overrides-z-NOT: attributes #0 = { {{.*}}ssp {{.*}} } - // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } - // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } - // basic: attributes #0 = { {{.*}}ssp {{.*}} } - // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } - // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } - - // basic-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } - // basic-z-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } - // basic-z: attributes #0 = { {{.*}}ssp {{.*}} } - // basic-z-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } - // basic-z-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } - // none-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } // none-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } // none-NOT: attributes #0 = { {{.*}}ssp {{.*}} } diff --git a/tests/ui/stack-protector/no-stack-protector-basic.rs b/tests/ui/stack-protector/no-stack-protector-basic.rs new file mode 100644 index 0000000000000..80f0e9b5d8c38 --- /dev/null +++ b/tests/ui/stack-protector/no-stack-protector-basic.rs @@ -0,0 +1,9 @@ +//@ check-fail +//@ revisions: stable unstable +//@ [unstable] compile-flags: -Z stack-protector=basic +//@ [stable] compile-flags: -C stack-protector=basic + +pub fn main(){} + +//[unstable]~? ERROR incorrect value `basic` for unstable option `stack-protector` +//[stable]~? ERROR incorrect value `basic` for codegen option `stack-protector` diff --git a/tests/ui/stack-protector/no-stack-protector-basic.stable.stderr b/tests/ui/stack-protector/no-stack-protector-basic.stable.stderr new file mode 100644 index 0000000000000..7295a2e9bd45a --- /dev/null +++ b/tests/ui/stack-protector/no-stack-protector-basic.stable.stderr @@ -0,0 +1,2 @@ +error: incorrect value `basic` for codegen option `stack-protector` - one of (`none` (default), `basic`, `strong`, or `all`) was expected + diff --git a/tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr b/tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr new file mode 100644 index 0000000000000..ce88114f16b82 --- /dev/null +++ b/tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr @@ -0,0 +1,2 @@ +error: incorrect value `basic` for unstable option `stack-protector` - one of (`none` (default), `basic`, `strong`, or `all`) was expected + From 0ebc35ef63daace18dfad43d7ea3ffd5198f776e Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 9 Sep 2025 13:39:48 +0000 Subject: [PATCH 3/9] change wording for stack-protector-strong --- compiler/rustc_codegen_llvm/src/lib.rs | 6 ++++-- src/doc/rustc/src/codegen-options/index.md | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 8e00581f65bae..b3ebddca60cb9 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -309,8 +309,10 @@ impl CodegenBackend for LlvmCodegenBackend { The exact rules are unstable and subject to change, but currently, it generates stack protectors for functions that, - *post-optimization*, contain either arrays (of any size - or type) or address-taken locals. + *post-optimization*, contain LLVM allocas (which + include all stack allocations - including fixed-size + allocations - that are used in a way that is not completely + determined by static control flow). none Do not generate stack canaries. diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 9924e35941e55..d360781aac69c 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -714,9 +714,11 @@ Supported values for this option are: The exact rules are unstable and subject to change, but currently, it generates stack protectors for functions that, - *post-optimization*, contain either arrays (of any size - or type) or address-taken locals. -- `all`: Generate stack canaries in all functions + *post-optimization*, contain LLVM allocas (which + include all stack allocations - including fixed-size + allocations - that are used in a way that is not completely + determined by static control flow). + - `all`: Generate stack canaries in all functions Stack protectors are not supported on many GPU targets, use of stack protectors on these targets is an error. From a37894686dff50d8d8f4affa27892ad30ec55a8b Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 9 Sep 2025 16:31:34 +0000 Subject: [PATCH 4/9] similar security guarnatees rather than exactly --- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- src/doc/rustc/src/codegen-options/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index b3ebddca60cb9..63723b6f5a31f 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -304,7 +304,7 @@ impl CodegenBackend for LlvmCodegenBackend { can prove these functions can't be the source of a stack buffer overflow (even in the presence of undefined behavior). - This provides the same security guarantees as Clang's + This provides similar security guarantees to Clang's `-fstack-protector=strong`. The exact rules are unstable and subject to change, but diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index d360781aac69c..a193b71c27df2 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -709,7 +709,7 @@ Supported values for this option are: can prove these functions can't be the source of a stack buffer overflow (even in the presence of undefined behavior). - This provides the same security guarantees as Clang's + This provides similar security guarantees to Clang's `-fstack-protector=strong`. The exact rules are unstable and subject to change, but From 5a729be39ed96641e3d75bec84404971d92deb51 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 10 Sep 2025 10:41:40 +0000 Subject: [PATCH 5/9] stack smash protection => stack smashing protection --- compiler/rustc_session/src/options.rs | 4 ++-- .../stack-protector-heuristics-effect-windows-32bit.rs | 4 ++-- .../stack-protector-heuristics-effect-windows-64bit.rs | 4 ++-- .../stack-protector/stack-protector-heuristics-effect.rs | 6 +++--- .../stack-protector/stack-protector-target-support.rs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index cd367fcb1fc12..1a521cee9cc81 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2216,7 +2216,7 @@ options! { "how to handle split-debuginfo, a platform-specific option"), #[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")] stack_protector: Option = (None, parse_stack_protector, [TRACKED], - "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), + "control stack smashing protection strategy (`rustc --print stack-protector-strategies` for details)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), symbol_mangling_version: Option = (None, @@ -2694,7 +2694,7 @@ written to standard error output)"), "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), #[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")] stack_protector: Option = (None, parse_stack_protector, [TRACKED], - "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), + "control stack smashing protection strategy (`rustc --print stack-protector-strategies` for details)"), staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED], "allow staticlibs to have rust dylib dependencies"), staticlib_prefer_dynamic: bool = (false, parse_bool, [TRACKED], diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index 493ed78ace15a..36355952f7db1 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -124,7 +124,7 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // This function takes the address of a local variable taken. Although this // address is never used as a way to refer to stack memory, the `strong` - // heuristic adds stack smash protection. This is also the case in C++: + // heuristic adds stack smashing protection. This is also the case in C++: // ``` // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk // #include @@ -180,7 +180,7 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // Even though the local variable conceptually has its address taken, as // it's passed by reference to the trait function, the use of the reference - // is easily inlined. There is therefore no stack smash protection even with + // is easily inlined. There is therefore no stack smashing protection even with // the `strong` heuristic. // all: __security_check_cookie diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index ce186c69432e6..6a5cd9cfaffd1 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -129,7 +129,7 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // This function takes the address of a local variable taken. Although this // address is never used as a way to refer to stack memory, the `strong` - // heuristic adds stack smash protection. This is also the case in C++: + // heuristic adds stack smashing protection. This is also the case in C++: // ``` // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk // #include @@ -186,7 +186,7 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // Even though the local variable conceptually has its address taken, as // it's passed by reference to the trait function, the use of the reference - // is easily inlined. There is therefore no stack smash protection even with + // is easily inlined. There is therefore no stack smashing protection even with // the `strong` heuristic. // all: __security_check_cookie diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs index 4b78a643b7b7b..f508896d7eb97 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs @@ -9,7 +9,7 @@ //@ [none] compile-flags: -C stack-protector=none //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -// NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR, +// NOTE: the heuristics for stack smashing protection inappropriately rely on types in LLVM IR, // despite those types having no semantic meaning. This means that the `basic` and `strong` // settings do not behave in a coherent way. This is a known issue in LLVM. // See comments on https://github.com/rust-lang/rust/issues/114903. @@ -120,7 +120,7 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // This function takes the address of a local variable taken. Although this // address is never used as a way to refer to stack memory, the `strong` - // heuristic adds stack smash protection. This is also the case in C++: + // heuristic adds stack smashing protection. This is also the case in C++: // ``` // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk // #include @@ -171,7 +171,7 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32 // Even though the local variable conceptually has its address taken, as // it's passed by reference to the trait function, the use of the reference - // is easily inlined. There is therefore no stack smash protection even with + // is easily inlined. There is therefore no stack smashing protection even with // the `strong` heuristic. // all: __stack_chk_fail diff --git a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs index c29f06cce16b8..71f4421b70830 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-target-support.rs @@ -1,4 +1,4 @@ -// Test that stack smash protection code is emitted for all tier1 and tier2 +// Test that stack smashing protection code is emitted for all tier1 and tier2 // targets, with the exception of nvptx64-nvidia-cuda // //@ add-minicore From 4a43f7739fe43ffa0b3d6f2c5e005c83e467162b Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 13 Sep 2025 15:58:18 +0000 Subject: [PATCH 6/9] add comments for why we dont have basic/plain mode --- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- src/doc/rustc/src/codegen-options/index.md | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 63723b6f5a31f..52000a8e887c0 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -305,7 +305,7 @@ impl CodegenBackend for LlvmCodegenBackend { buffer overflow (even in the presence of undefined behavior). This provides similar security guarantees to Clang's - `-fstack-protector=strong`. + `-fstack-protector-strong`. The exact rules are unstable and subject to change, but currently, it generates stack protectors for functions that, diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index a193b71c27df2..3b94827d89ae5 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -710,7 +710,7 @@ Supported values for this option are: buffer overflow (even in the presence of undefined behavior). This provides similar security guarantees to Clang's - `-fstack-protector=strong`. + `-fstack-protector-strong`. The exact rules are unstable and subject to change, but currently, it generates stack protectors for functions that, @@ -720,6 +720,15 @@ Supported values for this option are: determined by static control flow). - `all`: Generate stack canaries in all functions +rustc does not have a mode equivalent to Clang's (or GCC's) +plain `-fstack-protector` - `-fstack-protector` is an older heuristic +designed for C, that only protects functions that allocate a +`char buf[N];` buffer on the stack, making it prone to buffer overflows +from length miscalculations. This heuristic is poorly suited for Rust +code. Even in C codebases, `-fstack-protector-strong` is nowadays +preferred because plain `-fstack-protector` misses many stack +buffer overflows. + Stack protectors are not supported on many GPU targets, use of stack protectors on these targets is an error. From c59af15ec194cc296753130cac25823ebd826a0a Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 20 Nov 2025 15:28:22 +0000 Subject: [PATCH 7/9] remove warn-stack-protector-unsupported since we now fail on it --- .../warn-stack-protector-unsupported.rs | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.rs diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.rs b/tests/ui/stack-protector/warn-stack-protector-unsupported.rs deleted file mode 100644 index 9e0e126dabe66..0000000000000 --- a/tests/ui/stack-protector/warn-stack-protector-unsupported.rs +++ /dev/null @@ -1,31 +0,0 @@ -//@ build-pass -//@ revisions: all strong basic -//@ compile-flags: --target nvptx64-nvidia-cuda -//@ needs-llvm-components: nvptx -//@ [all] compile-flags: -Z stack-protector=all -//@ [strong] compile-flags: -Z stack-protector=strong -//@ [basic] compile-flags: -Z stack-protector=basic -//@ ignore-backends: gcc - -#![crate_type = "lib"] -#![feature(no_core, lang_items)] -#![no_std] -#![no_core] - -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -trait Sized: MetaSized {} - -#[lang = "copy"] -trait Copy {} - -pub fn main(){} - -//[all]~? WARN `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored -//[strong]~? WARN `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored -//[basic]~? WARN `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored From a320218a66cc5e7ab066e5e9e7b632de39972ffe Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 27 Nov 2025 19:28:10 +0000 Subject: [PATCH 8/9] ignore stack-protector test for gcc backend, see commit a8051a6ca37e --- tests/ui/stack-protector/fail-stack-protector-unsupported.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/stack-protector/fail-stack-protector-unsupported.rs b/tests/ui/stack-protector/fail-stack-protector-unsupported.rs index c9eb3560eda42..006c4b1d3a187 100644 --- a/tests/ui/stack-protector/fail-stack-protector-unsupported.rs +++ b/tests/ui/stack-protector/fail-stack-protector-unsupported.rs @@ -5,6 +5,7 @@ //@ [all] compile-flags: -C stack-protector=all //@ [strong] compile-flags: -C stack-protector=strong //@ [all-z] compile-flags: -Z stack-protector=all +//@ ignore-backends: gcc #![crate_type = "lib"] #![feature(no_core, lang_items)] From e3de165f0c4934a5acf994a2c2f123fecb40d667 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 11 Dec 2025 15:38:11 +0000 Subject: [PATCH 9/9] fix error message to not mention basic --- compiler/rustc_session/src/options.rs | 3 +-- .../ui/stack-protector/no-stack-protector-basic.stable.stderr | 2 +- .../stack-protector/no-stack-protector-basic.unstable.stderr | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 1a521cee9cc81..2c101de994b2d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -867,8 +867,7 @@ mod desc { pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`"; pub(crate) const parse_annotate_moves: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc.), or a size limit in bytes"; - pub(crate) const parse_stack_protector: &str = - "one of (`none` (default), `basic`, `strong`, or `all`)"; + pub(crate) const parse_stack_protector: &str = "one of (`none` (default), `strong`, or `all`)"; pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `gcs`, `pac-ret`, (optionally with `pc`, `b-key`, `leaf` if `pac-ret` is set)"; pub(crate) const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; diff --git a/tests/ui/stack-protector/no-stack-protector-basic.stable.stderr b/tests/ui/stack-protector/no-stack-protector-basic.stable.stderr index 7295a2e9bd45a..644c3e6a34f2a 100644 --- a/tests/ui/stack-protector/no-stack-protector-basic.stable.stderr +++ b/tests/ui/stack-protector/no-stack-protector-basic.stable.stderr @@ -1,2 +1,2 @@ -error: incorrect value `basic` for codegen option `stack-protector` - one of (`none` (default), `basic`, `strong`, or `all`) was expected +error: incorrect value `basic` for codegen option `stack-protector` - one of (`none` (default), `strong`, or `all`) was expected diff --git a/tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr b/tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr index ce88114f16b82..7ee0f6ae03f3d 100644 --- a/tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr +++ b/tests/ui/stack-protector/no-stack-protector-basic.unstable.stderr @@ -1,2 +1,2 @@ -error: incorrect value `basic` for unstable option `stack-protector` - one of (`none` (default), `basic`, `strong`, or `all`) was expected +error: incorrect value `basic` for unstable option `stack-protector` - one of (`none` (default), `strong`, or `all`) was expected