Set -Cpanic=abort in windows-msvc stack protector tests
This commit is contained in:
parent
2636cb4c13
commit
519785671b
3 changed files with 93 additions and 61 deletions
|
|
@ -7,7 +7,7 @@
|
|||
//@ [strong] compile-flags: -Z stack-protector=strong
|
||||
//@ [basic] compile-flags: -Z stack-protector=basic
|
||||
//@ [none] compile-flags: -Z stack-protector=none
|
||||
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
|
||||
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![allow(internal_features)]
|
||||
|
|
@ -26,6 +26,7 @@ pub fn emptyfn() {
|
|||
// CHECK-LABEL: array_char
|
||||
#[no_mangle]
|
||||
pub fn array_char(f: fn(*const char)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let a = ['c'; 1];
|
||||
let b = ['d'; 3];
|
||||
let c = ['e'; 15];
|
||||
|
|
@ -39,11 +40,14 @@ pub fn array_char(f: fn(*const char)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: array_u8_1
|
||||
#[no_mangle]
|
||||
pub fn array_u8_1(f: fn(*const u8)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let a = [0u8; 1];
|
||||
f(&a as *const _);
|
||||
|
||||
|
|
@ -55,11 +59,14 @@ pub fn array_u8_1(f: fn(*const u8)) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: array_u8_small:
|
||||
#[no_mangle]
|
||||
pub fn array_u8_small(f: fn(*const u8)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let a = [0u8; 2];
|
||||
let b = [0u8; 7];
|
||||
f(&a as *const _);
|
||||
|
|
@ -72,11 +79,14 @@ pub fn array_u8_small(f: fn(*const u8)) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: array_u8_large:
|
||||
#[no_mangle]
|
||||
pub fn array_u8_large(f: fn(*const u8)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let a = [0u8; 9];
|
||||
f(&a as *const _);
|
||||
|
||||
|
|
@ -88,6 +98,8 @@ pub fn array_u8_large(f: fn(*const u8)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
|
@ -96,6 +108,7 @@ pub struct ByteSizedNewtype(u8);
|
|||
// CHECK-LABEL: array_bytesizednewtype_9:
|
||||
#[no_mangle]
|
||||
pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let a = [ByteSizedNewtype(0); 9];
|
||||
f(&a as *const _);
|
||||
|
||||
|
|
@ -107,11 +120,14 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: local_var_addr_used_indirectly
|
||||
#[no_mangle]
|
||||
pub fn local_var_addr_used_indirectly(f: fn(bool)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let a = 5;
|
||||
let a_addr = &a as *const _ as usize;
|
||||
f(a_addr & 0x10 == 0);
|
||||
|
|
@ -134,37 +150,27 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: local_string_addr_taken
|
||||
#[no_mangle]
|
||||
pub fn local_string_addr_taken(f: fn(&String)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let x = String::new();
|
||||
f(&x);
|
||||
|
||||
// Taking the address of the local variable `x` leads to stack smash
|
||||
// protection with the `strong` heuristic, but not with the `basic`
|
||||
// heuristic. It does not matter that the reference is not mut.
|
||||
//
|
||||
// An interesting note is that a similar function in C++ *would* be
|
||||
// protected by the `basic` heuristic, because `std::string` has a char
|
||||
// array internally as a small object optimization:
|
||||
// ```
|
||||
// cat <<EOF | clang++ -O2 -fstack-protector -S -x c++ - -o - | grep stack_chk
|
||||
// #include <string>
|
||||
// void f(void (*g)(const std::string&)) {
|
||||
// std::string x;
|
||||
// g(x);
|
||||
// }
|
||||
// EOF
|
||||
// ```
|
||||
//
|
||||
// protection. It does not matter that the reference is not mut.
|
||||
|
||||
// all: __security_check_cookie
|
||||
// strong-NOT: __security_check_cookie
|
||||
// basic-NOT: __security_check_cookie
|
||||
// strong: __security_check_cookie
|
||||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
pub trait SelfByRef {
|
||||
|
|
@ -180,6 +186,7 @@ impl SelfByRef for i32 {
|
|||
// CHECK-LABEL: local_var_addr_taken_used_locally_only
|
||||
#[no_mangle]
|
||||
pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let x = factory();
|
||||
let g = x.f();
|
||||
sink(g);
|
||||
|
|
@ -194,6 +201,8 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
pub struct Gigastruct {
|
||||
|
|
@ -207,6 +216,7 @@ pub struct Gigastruct {
|
|||
// CHECK-LABEL: local_large_var_moved
|
||||
#[no_mangle]
|
||||
pub fn local_large_var_moved(f: fn(Gigastruct)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 };
|
||||
f(x);
|
||||
|
||||
|
|
@ -231,11 +241,14 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: local_large_var_cloned
|
||||
#[no_mangle]
|
||||
pub fn local_large_var_cloned(f: fn(Gigastruct)) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 });
|
||||
|
||||
// A new instance of `Gigastruct` is passed to `f()`, without any apparent
|
||||
|
|
@ -260,6 +273,8 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -293,6 +308,7 @@ extern "C" {
|
|||
// CHECK-LABEL: alloca_small_compile_time_constant_arg
|
||||
#[no_mangle]
|
||||
pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
f(unsafe { alloca(8) });
|
||||
|
||||
// all: __security_check_cookie
|
||||
|
|
@ -300,11 +316,14 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: alloca_large_compile_time_constant_arg
|
||||
#[no_mangle]
|
||||
pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
f(unsafe { alloca(9) });
|
||||
|
||||
// all: __security_check_cookie
|
||||
|
|
@ -312,11 +331,14 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: alloca_dynamic_arg
|
||||
#[no_mangle]
|
||||
pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
f(unsafe { alloca(n) });
|
||||
|
||||
// all: __security_check_cookie
|
||||
|
|
@ -324,18 +346,19 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
||||
// The question then is: in what ways can Rust code generate array-`alloca`
|
||||
// LLVM instructions? This appears to only be generated by
|
||||
// rustc_codegen_ssa::traits::Builder::array_alloca() through
|
||||
// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT
|
||||
// this is support for the "unsized locals" unstable feature:
|
||||
// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html.
|
||||
// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized().
|
||||
|
||||
// CHECK-LABEL: unsized_fn_param
|
||||
#[no_mangle]
|
||||
pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
|
||||
// CHECK-DAG: .cv_fpo_endprologue
|
||||
let n = if l { 1 } else { 2 };
|
||||
f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from
|
||||
|
||||
|
|
@ -346,14 +369,11 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
|
|||
// alloca, and is therefore not protected by the `strong` or `basic`
|
||||
// heuristics.
|
||||
|
||||
// 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
|
||||
// based EH personalities.
|
||||
// https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4
|
||||
// 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
|
||||
|
||||
// CHECK-DAG: .cv_fpo_endproc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
//@ [strong] compile-flags: -Z stack-protector=strong
|
||||
//@ [basic] compile-flags: -Z stack-protector=basic
|
||||
//@ [none] compile-flags: -Z stack-protector=none
|
||||
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
|
||||
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled -Cpanic=abort
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(unsized_fn_params)]
|
||||
|
|
@ -25,6 +25,7 @@ pub fn emptyfn() {
|
|||
// CHECK-LABEL: array_char
|
||||
#[no_mangle]
|
||||
pub fn array_char(f: fn(*const char)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let a = ['c'; 1];
|
||||
let b = ['d'; 3];
|
||||
let c = ['e'; 15];
|
||||
|
|
@ -38,11 +39,14 @@ pub fn array_char(f: fn(*const char)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: array_u8_1
|
||||
#[no_mangle]
|
||||
pub fn array_u8_1(f: fn(*const u8)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let a = [0u8; 1];
|
||||
f(&a as *const _);
|
||||
|
||||
|
|
@ -54,11 +58,14 @@ pub fn array_u8_1(f: fn(*const u8)) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: array_u8_small:
|
||||
#[no_mangle]
|
||||
pub fn array_u8_small(f: fn(*const u8)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let a = [0u8; 2];
|
||||
let b = [0u8; 7];
|
||||
f(&a as *const _);
|
||||
|
|
@ -71,11 +78,14 @@ pub fn array_u8_small(f: fn(*const u8)) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: array_u8_large:
|
||||
#[no_mangle]
|
||||
pub fn array_u8_large(f: fn(*const u8)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let a = [0u8; 9];
|
||||
f(&a as *const _);
|
||||
|
||||
|
|
@ -87,6 +97,8 @@ pub fn array_u8_large(f: fn(*const u8)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
|
@ -95,6 +107,7 @@ pub struct ByteSizedNewtype(u8);
|
|||
// CHECK-LABEL: array_bytesizednewtype_9:
|
||||
#[no_mangle]
|
||||
pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let a = [ByteSizedNewtype(0); 9];
|
||||
f(&a as *const _);
|
||||
|
||||
|
|
@ -106,11 +119,14 @@ pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: local_var_addr_used_indirectly
|
||||
#[no_mangle]
|
||||
pub fn local_var_addr_used_indirectly(f: fn(bool)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let a = 5;
|
||||
let a_addr = &a as *const _ as usize;
|
||||
f(a_addr & 0x10 == 0);
|
||||
|
|
@ -133,6 +149,8 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: local_string_addr_taken
|
||||
|
|
@ -143,31 +161,11 @@ pub fn local_string_addr_taken(f: fn(&String)) {
|
|||
f(&x);
|
||||
|
||||
// Taking the address of the local variable `x` leads to stack smash
|
||||
// protection with the `strong` heuristic, but not with the `basic`
|
||||
// heuristic. It does not matter that the reference is not mut.
|
||||
//
|
||||
// An interesting note is that a similar function in C++ *would* be
|
||||
// protected by the `basic` heuristic, because `std::string` has a char
|
||||
// array internally as a small object optimization:
|
||||
// ```
|
||||
// cat <<EOF | clang++ -O2 -fstack-protector -S -x c++ - -o - | grep stack_chk
|
||||
// #include <string>
|
||||
// void f(void (*g)(const std::string&)) {
|
||||
// std::string x;
|
||||
// g(x);
|
||||
// }
|
||||
// EOF
|
||||
// ```
|
||||
//
|
||||
// protection. It does not matter that the reference is not mut.
|
||||
|
||||
// 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
|
||||
// based EH personalities.
|
||||
// https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4
|
||||
// all-NOT: __security_check_cookie
|
||||
// strong-NOT: __security_check_cookie
|
||||
|
||||
// basic-NOT: __security_check_cookie
|
||||
// all: __security_check_cookie
|
||||
// strong: __security_check_cookie
|
||||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
|
|
@ -187,6 +185,7 @@ impl SelfByRef for i32 {
|
|||
// CHECK-LABEL: local_var_addr_taken_used_locally_only
|
||||
#[no_mangle]
|
||||
pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let x = factory();
|
||||
let g = x.f();
|
||||
sink(g);
|
||||
|
|
@ -201,6 +200,8 @@ pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
pub struct Gigastruct {
|
||||
|
|
@ -214,6 +215,7 @@ pub struct Gigastruct {
|
|||
// CHECK-LABEL: local_large_var_moved
|
||||
#[no_mangle]
|
||||
pub fn local_large_var_moved(f: fn(Gigastruct)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 };
|
||||
f(x);
|
||||
|
||||
|
|
@ -238,11 +240,14 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: local_large_var_cloned
|
||||
#[no_mangle]
|
||||
pub fn local_large_var_cloned(f: fn(Gigastruct)) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 });
|
||||
|
||||
// A new instance of `Gigastruct` is passed to `f()`, without any apparent
|
||||
|
|
@ -267,6 +272,8 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
|
|||
// basic: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -300,6 +307,7 @@ extern "C" {
|
|||
// CHECK-LABEL: alloca_small_compile_time_constant_arg
|
||||
#[no_mangle]
|
||||
pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
f(unsafe { alloca(8) });
|
||||
|
||||
// all: __security_check_cookie
|
||||
|
|
@ -307,11 +315,14 @@ pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: alloca_large_compile_time_constant_arg
|
||||
#[no_mangle]
|
||||
pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
f(unsafe { alloca(9) });
|
||||
|
||||
// all: __security_check_cookie
|
||||
|
|
@ -319,11 +330,14 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// CHECK-LABEL: alloca_dynamic_arg
|
||||
#[no_mangle]
|
||||
pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
f(unsafe { alloca(n) });
|
||||
|
||||
// all: __security_check_cookie
|
||||
|
|
@ -331,18 +345,19 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) {
|
|||
// basic-NOT: __security_check_cookie
|
||||
// none-NOT: __security_check_cookie
|
||||
// missing-NOT: __security_check_cookie
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
||||
// The question then is: in what ways can Rust code generate array-`alloca`
|
||||
// LLVM instructions? This appears to only be generated by
|
||||
// rustc_codegen_ssa::traits::Builder::array_alloca() through
|
||||
// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT
|
||||
// this is support for the "unsized locals" unstable feature:
|
||||
// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html.
|
||||
// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized().
|
||||
|
||||
// CHECK-LABEL: unsized_fn_param
|
||||
#[no_mangle]
|
||||
pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
|
||||
// CHECK-DAG: .seh_endprologue
|
||||
let n = if l { 1 } else { 2 };
|
||||
f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from
|
||||
|
||||
|
|
@ -353,14 +368,11 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
|
|||
// alloca, and is therefore not protected by the `strong` or `basic`
|
||||
// heuristics.
|
||||
|
||||
// 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
|
||||
// based EH personalities.
|
||||
// https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4
|
||||
// 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
|
||||
|
||||
// CHECK-DAG: .seh_endproc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//@ compile-flags: -Z stack-protector=all -Cpanic=abort
|
||||
//@ compile-flags: -C opt-level=2
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue