Skip to content

Commit

Permalink
rune: Use a sentinel value when accessing the stack oob
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Nov 5, 2024
1 parent 02e6344 commit 16b4402
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 85 deletions.
2 changes: 1 addition & 1 deletion crates/rune/src/runtime/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ where
count,
InstAddress::ZERO.output()
));
vm_try!(stack.at(InstAddress::ZERO)).clone()
stack.at(InstAddress::ZERO).clone()
}
Inner::FnOffset(fn_offset) => {
vm_try!(fn_offset.call(args, ()))
Expand Down
4 changes: 2 additions & 2 deletions crates/rune/src/runtime/protocol_caller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl ProtocolCaller for EnvProtocolCaller {
vm_try!(stack.push(target));
vm_try!(args.push_to_stack(&mut stack));
vm_try!(handler(&mut stack, addr, count, addr.output()));
let value = vm_try!(stack.at(addr)).clone();
let value = stack.at(addr).clone();
return VmResult::Ok(CallResultOnly::Ok(value));
}

Expand Down Expand Up @@ -112,7 +112,7 @@ impl ProtocolCaller for Vm {
)) {
CallResult::Unsupported(value) => VmResult::Ok(CallResultOnly::Unsupported(value)),
CallResult::Ok(()) => {
let value = vm_try!(self.stack().at(addr)).clone();
let value = self.stack().at(addr).clone();
self.stack_mut().truncate(addr);
VmResult::Ok(CallResultOnly::Ok(value))
}
Expand Down
14 changes: 11 additions & 3 deletions crates/rune/src/runtime/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ use crate::alloc::prelude::*;
use crate::alloc::{self, Vec};
use crate::runtime::{InstAddress, Output, Value, VmErrorKind};

// This is a bit tricky. We know that `Value::empty()` is `Sync` but we can't
// convince Rust that is the case.
struct AssertSync<T>(T);
unsafe impl<T> Sync for AssertSync<T> {}

static EMPTY: AssertSync<Value> = AssertSync(Value::empty());

/// An error raised when accessing an address on the stack.
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
Expand Down Expand Up @@ -234,16 +241,17 @@ impl Stack {
/// use rune::runtime::{Output, Stack, VmResult, InstAddress};
///
/// fn add_one(stack: &mut Stack, addr: InstAddress, args: usize, out: Output) -> VmResult<()> {
/// let value = vm_try!(vm_try!(stack.at(addr)).as_integer::<i64>());
/// let value = vm_try!(stack.at(addr).as_integer::<i64>());
/// out.store(stack, value + 1);
/// VmResult::Ok(())
/// }
/// ```
pub fn at(&self, addr: InstAddress) -> Result<&Value, StackError> {
#[inline(always)]
pub fn at(&self, addr: InstAddress) -> &Value {
self.top
.checked_add(addr.offset())
.and_then(|n| self.stack.get(n))
.ok_or(StackError { addr })
.unwrap_or(&EMPTY.0)
}

/// Get a value mutable at the given index from the stack bottom.
Expand Down
Loading

0 comments on commit 16b4402

Please sign in to comment.