Make clearing value stack between export invocations optional (#188)

This avoids the main overhead of repeated export invocations by making
it optional to clear the value stack after each interpreter run.

This is especially useful if different exports of the same module are
invoked repeated so that no unintended information leaks are possible.
This commit is contained in:
adam-rhebo 2019-06-21 11:03:58 +02:00 committed by Sergei Pepyakin
parent 7fe6ef4e35
commit f29f301e6e
1 changed files with 16 additions and 4 deletions

View File

@ -1493,6 +1493,22 @@ impl StackRecycler {
} }
} }
/// Clears any values left on the stack to avoid
/// leaking them to future export invocations.
///
/// This is a secondary defense to prevent modules from
/// exploiting faulty stack handling in the interpreter.
///
/// Do note that there are additional channels that
/// can leak information into an untrusted module.
pub fn clear(&mut self) {
if let Some(buf) = &mut self.value_stack_buf {
for cell in buf.iter_mut() {
*cell = RuntimeValueInternal(0);
}
}
}
fn recreate_value_stack(this: &mut Option<&mut Self>) -> ValueStack { fn recreate_value_stack(this: &mut Option<&mut Self>) -> ValueStack {
let limit = this let limit = this
.as_ref() .as_ref()
@ -1526,10 +1542,6 @@ impl StackRecycler {
} }
pub(crate) fn recycle(&mut self, mut interpreter: Interpreter) { pub(crate) fn recycle(&mut self, mut interpreter: Interpreter) {
for cell in interpreter.value_stack.buf.iter_mut() {
*cell = RuntimeValueInternal(0);
}
interpreter.call_stack.buf.clear(); interpreter.call_stack.buf.clear();
self.value_stack_buf = Some(interpreter.value_stack.buf); self.value_stack_buf = Some(interpreter.value_stack.buf);