fix(vm): make sure that we only jump to jump targets

This commit is contained in:
Alain Zscheile 2022-09-23 18:44:43 +02:00
parent 14e809e0a6
commit 94117e5817
2 changed files with 37 additions and 4 deletions

View file

@ -2,7 +2,7 @@ use crate::consts::{AtomOp, MathBinOp, OpType};
use crate::{Atom, Value};
use core::fmt;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Instr<'a> {
// control flow
/// defines a destination label

View file

@ -11,19 +11,30 @@ struct Module {
type InstrPtr = (Arc<Module>, usize);
trait Origin: Send + Sync + core::fmt::Debug {
fn call(&self, instrp: &mut InstrPtr, p: &Pointer, a: &Atom);
fn call(&self, p: &Pointer, a: &Atom) -> InstrPtr;
fn incr_refcount(&self, p: &Pointer);
fn decr_refcount(&self, p: &Pointer);
}
static NOOP_MODULE: Lazy<Arc<Module>> = Lazy::new(|| {
let mut v = Vec::new();
use fogtix_bytecode::Instr;
Instr::Label.write_to(&mut v).unwrap();
Instr::Return.write_to(&mut v).unwrap();
Arc::new(Module {
h: readfilez::FileHandle::Buffered(v),
})
});
#[derive(Debug)]
struct NoopOrigin;
impl Origin for NoopOrigin {
fn call(&self, _instrp: &mut InstrPtr, p: &Pointer, a: &Atom) {
fn call(&self, p: &Pointer, a: &Atom) -> InstrPtr {
eprintln!(
"WARN: tried to invoke pointer {:?}({:?}) without valid context",
p, a
);
(Arc::clone(&NOOP_MODULE), 0)
}
fn incr_refcount(&self, _p: &Pointer) {}
fn decr_refcount(&self, _p: &Pointer) {}
@ -119,7 +130,7 @@ impl Process {
break;
}
Some(StackEntValue::Pointer(wp)) => {
wp.orig.call(&mut self.instrp, &wp.p, &atom);
self.instrp = wp.orig.call(&wp.p, &atom);
}
Some(x) => {
eprintln!(
@ -129,6 +140,17 @@ impl Process {
break;
}
}
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
if trgi != Instr::Label {
eprintln!(
"ERROR: `call` arrived at non-jump target {:?} @ {}",
trgi, previptr
);
break;
}
}
}
}
Instr::Jump(x) => {
self.instrp.1 = match x.try_into() {
@ -140,6 +162,17 @@ impl Process {
);
break;
}
};
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
if trgi != Instr::Label {
eprintln!(
"ERROR: jump arrived at non-jump target {:?} @ {}",
trgi, previptr
);
break;
}
}
}
}
Instr::Return => match self.callstack.pop() {