~: function calls should be restricted in input arity

This commit is contained in:
Alain Zscheile 2022-09-23 19:41:37 +02:00
parent 94117e5817
commit 17efdff6f5
2 changed files with 19 additions and 8 deletions

View file

@ -10,7 +10,8 @@ pub enum Instr<'a> {
/// pops the descriptor table pointer from the stack,
/// then tries to call the $0 on it.
Call(Atom),
/// $1 is the amount of arguments (arity) extracted from the stack after the pointer
Call(Atom, u8),
/// jumps to the destination $0 inside of the current module
Jump(u64),
@ -43,7 +44,7 @@ impl Instr<'_> {
pub fn typ(&self) -> OpType {
match self {
Instr::Label => OpType::Label,
Instr::Call(_) => OpType::Call,
Instr::Call(_, _) => OpType::Call,
Instr::Jump(_) => OpType::Jump,
Instr::Return => OpType::Return,
Instr::Push(_) => OpType::Push,
@ -89,7 +90,11 @@ impl<'a> crate::Parse<'a> for Instr<'a> {
}
let (inp, otyp) = OpType::parse(inp)?;
match otyp {
OpType::Call => Atom::parse(inp).map(|(inp, val)| (inp, Instr::Call(val))),
OpType::Call => {
let (inp, val) = Atom::parse(inp)?;
let (inp, arity) = u8::parse(inp)?;
Ok((inp, Instr::Call(val, arity)))
}
OpType::Jump => u64::parse(inp).map(|(inp, val)| (inp, Instr::Jump(val))),
OpType::Push => Ok(Value::parse(inp).map(|(inp, val)| (inp, Instr::Push(val)))?),
OpType::Pop => u32::parse(inp).map(|(inp, val)| (inp, Instr::Pop(val))),
@ -110,7 +115,10 @@ impl Instr<'_> {
use int_enum::IntEnum;
writer.write_all(&self.typ().int_value().to_be_bytes())?;
match self {
Instr::Call(val) => val.write_to(writer)?,
Instr::Call(val, arity) => {
val.write_to(&mut writer)?;
writer.write_all(&[*arity])?;
}
Instr::Jump(val) => writer.write_all(&val.to_be_bytes())?,
Instr::Push(val) => val.write_to(writer)?,
Instr::Pop(val) => writer.write_all(&val.to_be_bytes())?,

View file

@ -11,7 +11,7 @@ struct Module {
type InstrPtr = (Arc<Module>, usize);
trait Origin: Send + Sync + core::fmt::Debug {
fn call(&self, p: &Pointer, a: &Atom) -> InstrPtr;
fn call(&self, p: &Pointer, a: &Atom, stack: &mut Vec<StackEntValue>) -> InstrPtr;
fn incr_refcount(&self, p: &Pointer);
fn decr_refcount(&self, p: &Pointer);
}
@ -29,7 +29,7 @@ static NOOP_MODULE: Lazy<Arc<Module>> = Lazy::new(|| {
#[derive(Debug)]
struct NoopOrigin;
impl Origin for NoopOrigin {
fn call(&self, p: &Pointer, a: &Atom) -> InstrPtr {
fn call(&self, p: &Pointer, a: &Atom, _stack: &mut Vec<StackEntValue>) -> InstrPtr {
eprintln!(
"WARN: tried to invoke pointer {:?}({:?}) without valid context",
p, a
@ -113,7 +113,7 @@ impl Process {
self.instrp.1 += nxtiptr.len() - nxti_arr.len();
match nxti {
Instr::Label => {}
Instr::Call(atom) => {
Instr::Call(atom, arity) => {
let mut call2jump = false;
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
if let Ok((_, Instr::Return)) = Instr::parse(n2xti_arr) {
@ -130,7 +130,10 @@ impl Process {
break;
}
Some(StackEntValue::Pointer(wp)) => {
self.instrp = wp.orig.call(&wp.p, &atom);
let ssl = self.stack.len();
let mut args = self.stack.drain(ssl - usize::from(arity)..).collect();
self.instrp = wp.orig.call(&wp.p, &atom, &mut args);
self.stack.extend(args);
}
Some(x) => {
eprintln!(