Disable runtime split stack support on Windows

This commit is contained in:
Brian Anderson 2014-09-24 15:35:44 -07:00
parent 91e30ecf67
commit a52eaaa996
3 changed files with 13 additions and 56 deletions

View file

@ -200,11 +200,7 @@ pub unsafe fn record_sp_limit(limit: uint) {
asm!("movq $0, %fs:112" :: "r"(limit) :: "volatile")
}
#[cfg(target_arch = "x86_64", target_os = "windows")] #[inline(always)]
unsafe fn target_record_sp_limit(limit: uint) {
// see: http://en.wikipedia.org/wiki/Win32_Thread_Information_Block
// store this inside of the "arbitrary data slot", but double the size
// because this is 64 bit instead of 32 bit
asm!("movq $0, %gs:0x28" :: "r"(limit) :: "volatile")
unsafe fn target_record_sp_limit(_: uint) {
}
#[cfg(target_arch = "x86_64", target_os = "freebsd")] #[inline(always)]
unsafe fn target_record_sp_limit(limit: uint) {
@ -228,10 +224,7 @@ pub unsafe fn record_sp_limit(limit: uint) {
asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile")
}
#[cfg(target_arch = "x86", target_os = "windows")] #[inline(always)]
unsafe fn target_record_sp_limit(limit: uint) {
// see: http://en.wikipedia.org/wiki/Win32_Thread_Information_Block
// store this inside of the "arbitrary data slot"
asm!("movl $0, %fs:0x14" :: "r"(limit) :: "volatile")
unsafe fn target_record_sp_limit(_: uint) {
}
// mips, arm - Some brave soul can port these to inline asm, but it's over
@ -282,9 +275,7 @@ pub unsafe fn get_sp_limit() -> uint {
}
#[cfg(target_arch = "x86_64", target_os = "windows")] #[inline(always)]
unsafe fn target_get_sp_limit() -> uint {
let limit;
asm!("movq %gs:0x28, $0" : "=r"(limit) ::: "volatile");
return limit;
return 1024;
}
#[cfg(target_arch = "x86_64", target_os = "freebsd")] #[inline(always)]
unsafe fn target_get_sp_limit() -> uint {
@ -318,9 +309,7 @@ pub unsafe fn get_sp_limit() -> uint {
}
#[cfg(target_arch = "x86", target_os = "windows")] #[inline(always)]
unsafe fn target_get_sp_limit() -> uint {
let limit;
asm!("movl %fs:0x14, $0" : "=r"(limit) ::: "volatile");
return limit;
return 1024;
}
// mips, arm - Some brave soul can port these to inline asm, but it's over

View file

@ -136,7 +136,6 @@ mod imp {
use os;
use rand::Rng;
use result::{Ok, Err};
use rt::stack;
use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
use self::libc::types::os::arch::extra::{LONG_PTR};
use slice::MutableSlice;
@ -159,7 +158,6 @@ mod imp {
static PROV_RSA_FULL: DWORD = 1;
static CRYPT_SILENT: DWORD = 64;
static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
#[allow(non_snake_case)]
extern "system" {
@ -178,48 +176,12 @@ mod imp {
/// Create a new `OsRng`.
pub fn new() -> IoResult<OsRng> {
let mut hcp = 0;
let mut ret = unsafe {
let ret = unsafe {
CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
};
// FIXME #13259:
// It turns out that if we can't acquire a context with the
// NTE_BAD_SIGNATURE error code, the documentation states:
//
// The provider DLL signature could not be verified. Either the
// DLL or the digital signature has been tampered with.
//
// Sounds fishy, no? As it turns out, our signature can be bad
// because our Thread Information Block (TIB) isn't exactly what it
// expects. As to why, I have no idea. The only data we store in the
// TIB is the stack limit for each thread, but apparently that's
// enough to make the signature valid.
//
// Furthermore, this error only happens the *first* time we call
// CryptAcquireContext, so we don't have to worry about future
// calls.
//
// Anyway, the fix employed here is that if we see this error, we
// pray that we're not close to the end of the stack, temporarily
// set the stack limit to 0 (what the TIB originally was), acquire a
// context, and then reset the stack limit.
//
// Again, I'm not sure why this is the fix, nor why we're getting
// this error. All I can say is that this seems to allow libnative
// to progress where it otherwise would be hindered. Who knew?
if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
unsafe {
let limit = stack::get_sp_limit();
stack::record_sp_limit(0);
ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
stack::record_sp_limit(limit);
}
}
if ret == 0 {
Err(IoError::last_error())
} else {

View file

@ -42,11 +42,17 @@ fn main() {
let silent = Command::new(args[0].as_slice()).arg("silent").output().unwrap();
assert!(!silent.status.success());
let error = String::from_utf8_lossy(silent.error.as_slice());
assert!(error.as_slice().contains("has overflowed its stack"));
// FIXME #17562: Windows is using stack probes and isn't wired up to print an error
if !cfg!(windows) {
assert!(error.as_slice().contains("has overflowed its stack"));
}
let loud = Command::new(args[0].as_slice()).arg("loud").output().unwrap();
assert!(!loud.status.success());
let error = String::from_utf8_lossy(silent.error.as_slice());
assert!(error.as_slice().contains("has overflowed its stack"));
// FIXME #17562: Windows is using stack probes and isn't wired up to print an error
if !cfg!(windows) {
assert!(error.as_slice().contains("has overflowed its stack"));
}
}
}