Skip to content

Commit

Permalink
Use the psm crate to figure out the current stack pointer (#2358)
Browse files Browse the repository at this point in the history
Currently the runtime needs to acquire the current stack pointer so it
can set a limit for where if the wasm stack goes below that point it
will abort the wasm code. Acquiring the stack pointer is done in a
brittle way right now which involves looking at the address of what we
hope is an on-stack structure. This turns out to not work at all with
ASan as well.

Instead this commit switches to the `psm` crate which is used by the
Rust compiler team for stack manipulation, namely a coarse version of
segmented stacks to avoid stack overflow in the compiler. We don't need
most of the implementation of `psm`, just the `stack_pointer` function,
but it shouldn't be a burden to bring in!

Closes #2344
  • Loading branch information
alexcrichton authored Nov 5, 2020
1 parent 6b137c2 commit ea3306e
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 3 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ more-asserts = "0.2.1"
cfg-if = "1.0"
backtrace = "0.3.49"
lazy_static = "1.3.0"
psm = "0.1.11"

[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.7", features = ["winbase", "memoryapi", "errhandlingapi"] }
Expand Down
15 changes: 12 additions & 3 deletions crates/runtime/src/traphandlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,18 @@ impl<'a> CallThreadState<'a> {
/// Note that this function must be called with `self` on the stack, not the
/// heap/etc.
fn update_stack_limit(&self, max_wasm_stack: usize) -> Result<impl Drop + '_, Trap> {
// Make an "educated guess" to figure out where the wasm sp value should
// start trapping if it drops below.
let wasm_stack_limit = self as *const _ as usize - max_wasm_stack;
// Determine the stack pointer where, after which, any wasm code will
// immediately trap. This is checked on the entry to all wasm functions.
//
// Note that this isn't 100% precise. We are requested to give wasm
// `max_wasm_stack` bytes, but what we're actually doing is giving wasm
// probably a little less than `max_wasm_stack` because we're
// calculating the limit relative to this function's approximate stack
// pointer. Wasm will be executed on a frame beneath this one (or next
// to it). In any case it's expected to be at most a few hundred bytes
// of slop one way or another. When wasm is typically given a MB or so
// (a million bytes) the slop shouldn't matter too much.
let wasm_stack_limit = psm::stack_pointer() as usize - max_wasm_stack;

let interrupts = unsafe { &**(&*self.vmctx).instance().interrupts() };
let reset_stack_limit = match interrupts.stack_limit.compare_exchange(
Expand Down

0 comments on commit ea3306e

Please sign in to comment.