Skip to content

Commit

Permalink
Add check for bytecode depth
Browse files Browse the repository at this point in the history
  • Loading branch information
CeleritasCelery committed Dec 26, 2023
1 parent 3fe50e4 commit 9dbda4f
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 32 deletions.
19 changes: 15 additions & 4 deletions src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,8 @@ impl<'ob> RootedVM<'_, '_, '_> {
let old = self.frame.bind_mut(cx);
std::mem::swap(old, &mut new);
self.call_frames.push(new);
let frame_start = dbg!(len) - (dbg!(arg_cnt) + 1);
self.env.stack.push_frame(frame_start);
let frame_start = len - (arg_cnt + 1);
self.env.stack.push_frame(frame_start, f.depth);
self.prepare_lisp_args(f, arg_cnt as u16, &name, cx)?;
} else {
// Otherwise, call the function directly.
Expand Down Expand Up @@ -897,7 +897,7 @@ pub(crate) fn call<'ob>(
cx: &'ob mut Context,
) -> EvalResult<'ob> {
let len = env.stack.len();
env.stack.push_frame(len);
env.stack.push_frame(len, func.bind(cx).depth);
for arg in args {
env.stack.push(arg.bind(cx));
}
Expand Down Expand Up @@ -941,7 +941,18 @@ mod test {
println!("Test seq: {opcodes:?}");
opcodes.into_obj(cx1).untag()
};
let bytecode = crate::alloc::make_byte_code($arglist, &opcodes, constants, 0, None, None, &[], cx1).unwrap();
// TODO: we should probably caculate the actual depth
let depth = 10;
let bytecode = crate::alloc::make_byte_code(
$arglist,
&opcodes,
constants,
depth,
None,
None,
&[],
cx1
).unwrap();
root!(bytecode, cx1);
let $name = bytecode;
)
Expand Down
50 changes: 32 additions & 18 deletions src/core/env/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ use std::ops::{Index, IndexMut, RangeTo};
pub(crate) struct LispStack<'a> {
vec: Vec<GcObj<'a>>,
#[no_trace]
start: usize,
current: Frame,
#[no_trace]
frame_starts: Vec<usize>,
frames: Vec<Frame>,
}

#[derive(Debug, Default, Clone, Copy)]
struct Frame {
start: usize,
end: usize,
}

// To make this simpler we implement indexing from the top of the stack (end of
Expand Down Expand Up @@ -57,59 +63,67 @@ impl<'a> Index<RangeTo<usize>> for RootedLispStack<'a> {
}

impl<'a> RootedLispStack<'a> {
pub(crate) fn push_frame(&mut self, start: usize) {
pub(crate) fn push_frame(&mut self, start: usize, depth: usize) {
assert!(start <= self.len());
assert!(self.start <= start);
self.frame_starts.push(self.start);
self.start = start;
assert!(self.current.start <= start);
self.frames.push(self.current);
let end = start + depth;
// allocate space so that we don't have to reallocate later. This will
// also let us do unchecked pushes later.
if end > self.vec.capacity() {
self.vec.reserve(end - self.vec.len());
}
self.current = Frame { start, end };
}

pub(crate) fn pop_frame(&mut self) {
self.vec.truncate(self.start);
self.start = self.frame_starts.pop().unwrap();
self.vec.truncate(self.current.start);
self.current = self.frames.pop().unwrap();
}

pub(crate) fn return_frame(&mut self) {
self.vec.swap_remove(self.start);
self.vec.truncate(self.start + 1);
self.start = self.frame_starts.pop().unwrap();
self.vec.swap_remove(self.current.start);
self.vec.truncate(self.current.start + 1);
self.current = self.frames.pop().unwrap();
}

pub(crate) fn current_frame(&self) -> usize {
self.frame_starts.len()
self.frames.len()
}

pub(crate) fn unwind_frames(&mut self, frame: usize) {
if frame == self.current_frame() {
return; /* no frames to unwind */
}
assert!(frame < self.current_frame());
self.start = self.frame_starts[frame];
self.frame_starts.truncate(frame);
self.current = self.frames[frame];
self.frames.truncate(frame);
}

pub(crate) fn len(&self) -> usize {
self.vec.len()
}

pub(crate) fn push(&mut self, value: GcObj) {
assert!(self.len() < self.current.end);
// could use https://github.com/rust-lang/rust/issues/100486
self.vec.push(value);
}

pub(crate) fn pop<'ob>(&mut self, cx: &'ob Context) -> GcObj<'ob> {
assert!(self.len() > self.start);
assert!(self.len() > self.current.start);
self.vec.bind_mut(cx).pop().unwrap()
}

pub(crate) fn top(&mut self) -> &mut Rt<GcObj<'a>> {
assert!(self.len() > self.start);
assert!(self.len() > self.current.start);
self.vec.last_mut().unwrap()
}

pub(crate) fn offset_end(&self, i: usize) -> usize {
assert!(i < self.len());
let from_end = self.len() - (i + 1);
assert!(self.start <= from_end);
assert!(self.current.start <= from_end);
from_end
}

Expand Down Expand Up @@ -140,6 +154,6 @@ impl<'a> RootedLispStack<'a> {
}

pub(crate) fn frame_iter(&self) -> impl Iterator<Item = &Rt<GcObj>> {
self.vec[self.start..].iter().rev()
self.vec[self.current.start..].iter().rev()
}
}
17 changes: 7 additions & 10 deletions src/core/env/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@ use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};

/// The allocation of a global symbol. This is shared
/// between threads, so the interned value of a symbol
/// will be the same location no matter which thread
/// interned it. Functions are safe to share between
/// threads because they are marked immutable by
/// [`ObjectMap::set_func`](`crate::core::env::ObjectMap::set_func`)
/// and they can only be replaced atomically.
/// In order to garbage collect the function we need to
/// halt all running threads. This has not been implemented
/// yet.
/// The allocation of a global symbol. This is shared between threads, so the
/// interned value of a symbol will be the same location no matter which thread
/// interned it. Functions are safe to share between threads because they are
/// marked immutable by
/// [`ObjectMap::set_func`](`crate::core::env::ObjectMap::set_func`) and they
/// can only be replaced atomically. In order to garbage collect the function we
/// need to halt all running threads. This has not been implemented yet.
pub(crate) struct SymbolCell {
name: SymbolName,
// Global symbols are always immutable, so we mark them so they are not
Expand Down
8 changes: 8 additions & 0 deletions src/core/gc/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,14 @@ impl<T> Rt<Vec<T>> {
pub(crate) fn swap_remove(&mut self, index: usize) {
self.as_mut_ref().swap_remove(index);
}

pub(crate) fn reserve(&mut self, additional: usize) {
self.as_mut_ref().reserve(additional);
}

pub(crate) fn capacity(&self) -> usize {
self.inner.capacity()
}
}

impl<T> Deref for Rt<Vec<T>> {
Expand Down

0 comments on commit 9dbda4f

Please sign in to comment.