Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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
  • Loading branch information
Ariel Ben-Yehuda committed Sep 13, 2025
commit daca88a64ed10e71e341d70b53425355aa49b23b
3 changes: 1 addition & 2 deletions bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,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.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
StackProtector::None => return None,
StackProtector::All => AttributeKind::StackProtectReq,
StackProtector::Strong => AttributeKind::StackProtectStrong,
StackProtector::Basic => AttributeKind::StackProtect,
};

Some(sspattr.create_attr(cx.llcx))
Expand Down
14 changes: 0 additions & 14 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,20 +294,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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's not widely used by Clang/Gcc, but should we add why the basic mode/strategy is not applicable to Rust and thus not available in case people look for it for matching build configurations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that outside of rustc it's always called -fstack-protector (rather than "basic stack protection", which is not a name I've ever heard outside of a Rust context), but I agree that it makes sense to have documentation for why it does not exist. I think only in the markdown file, rather than in this file (tho I have no problem putting it in both places).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agreed. I actually meant mainly in the markdown docs, but left the comment in the wrong place. Something like: -fstack-protector or -fstack-protector=basic is not available/applicable to Rust because... (or equivalent to it). What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, will do that soon-ish.

"#
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1347,12 +1347,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
Expand Down
2 changes: 0 additions & 2 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -682,8 +682,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).
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
}
Expand All @@ -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
}
Expand All @@ -52,7 +49,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
}
Expand All @@ -66,10 +62,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
}
Expand All @@ -82,10 +78,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
}
Expand All @@ -101,10 +97,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
}
Expand All @@ -128,10 +124,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
}
Expand Down Expand Up @@ -159,10 +155,10 @@ pub fn local_string_addr_taken(f: fn(&String)) {
// EOF
// ```
//
// (basic is not currently supported, leaving the test anyway).

// all: __security_check_cookie
// strong-NOT: __security_check_cookie
// basic-NOT: __security_check_cookie
// none-NOT: __security_check_cookie
// missing-NOT: __security_check_cookie
}
Expand Down Expand Up @@ -191,7 +187,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
}
Expand Down Expand Up @@ -228,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
}
Expand Down Expand Up @@ -257,7 +251,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
}
Expand Down Expand Up @@ -297,7 +290,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
}
Expand All @@ -309,7 +301,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
}
Expand All @@ -321,7 +312,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
}
Expand Down Expand Up @@ -353,7 +343,6 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
// 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
}
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
}
Expand All @@ -35,7 +33,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
}
Expand All @@ -51,7 +48,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
}
Expand All @@ -65,10 +61,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
}
Expand All @@ -81,10 +77,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
}
Expand All @@ -100,10 +96,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
}
Expand All @@ -130,7 +126,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
}
Expand Down Expand Up @@ -158,7 +153,6 @@ pub fn local_string_addr_taken(f: fn(&String)) {
// }
// EOF
// ```
//

// We should have a __security_check_cookie call in `all` and `strong` modes but
// LLVM does not support generating stack protectors in functions with funclet
Expand All @@ -167,7 +161,6 @@ pub fn local_string_addr_taken(f: fn(&String)) {
// 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

Expand Down Expand Up @@ -198,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
}
Expand Down Expand Up @@ -235,7 +227,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
}
Expand Down Expand Up @@ -264,7 +255,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
}
Expand Down Expand Up @@ -304,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
}
Expand All @@ -316,7 +305,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
}
Expand All @@ -328,7 +316,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
}
Expand Down Expand Up @@ -360,7 +347,6 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
// 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
}
Loading