mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-18 09:21:49 +00:00
Clean
This commit is contained in:
@ -21,7 +21,7 @@ const DEFAULT_VALUE_STACK_LIMIT: usize = 16384;
|
|||||||
const DEFAULT_FRAME_STACK_LIMIT: usize = 1024;
|
const DEFAULT_FRAME_STACK_LIMIT: usize = 1024;
|
||||||
|
|
||||||
/// Function validation context.
|
/// Function validation context.
|
||||||
pub struct FunctionValidationContext<'a> {
|
struct FunctionValidationContext<'a> {
|
||||||
/// Wasm module
|
/// Wasm module
|
||||||
module: &'a ModuleContext,
|
module: &'a ModuleContext,
|
||||||
/// Current instruction position.
|
/// Current instruction position.
|
||||||
@ -40,7 +40,7 @@ pub struct FunctionValidationContext<'a> {
|
|||||||
|
|
||||||
/// Value type on the stack.
|
/// Value type on the stack.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum StackValueType {
|
enum StackValueType {
|
||||||
/// Any value type.
|
/// Any value type.
|
||||||
Any,
|
Any,
|
||||||
/// Any number of any values of any type.
|
/// Any number of any values of any type.
|
||||||
@ -54,7 +54,7 @@ pub struct Validator;
|
|||||||
|
|
||||||
/// Instruction outcome.
|
/// Instruction outcome.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum InstructionOutcome {
|
enum InstructionOutcome {
|
||||||
/// Continue with next instruction.
|
/// Continue with next instruction.
|
||||||
ValidateNextInstruction,
|
ValidateNextInstruction,
|
||||||
/// Unreachable instruction reached.
|
/// Unreachable instruction reached.
|
||||||
@ -590,7 +590,7 @@ impl Validator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FunctionValidationContext<'a> {
|
impl<'a> FunctionValidationContext<'a> {
|
||||||
pub fn new(
|
fn new(
|
||||||
module: &'a ModuleContext,
|
module: &'a ModuleContext,
|
||||||
locals: &'a [ValueType],
|
locals: &'a [ValueType],
|
||||||
value_stack_limit: usize,
|
value_stack_limit: usize,
|
||||||
@ -608,11 +608,11 @@ impl<'a> FunctionValidationContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
|
fn push_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
|
||||||
Ok(self.value_stack.push(value_type.into())?)
|
Ok(self.value_stack.push(value_type.into())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
|
fn pop_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
|
||||||
self.check_stack_access()?;
|
self.check_stack_access()?;
|
||||||
match self.value_stack.pop()? {
|
match self.value_stack.pop()? {
|
||||||
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()),
|
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()),
|
||||||
@ -625,7 +625,7 @@ impl<'a> FunctionValidationContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tee_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
|
fn tee_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
|
||||||
self.check_stack_access()?;
|
self.check_stack_access()?;
|
||||||
match *self.value_stack.top()? {
|
match *self.value_stack.top()? {
|
||||||
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()),
|
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()),
|
||||||
@ -634,7 +634,7 @@ impl<'a> FunctionValidationContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_any_value(&mut self) -> Result<StackValueType, Error> {
|
fn pop_any_value(&mut self) -> Result<StackValueType, Error> {
|
||||||
self.check_stack_access()?;
|
self.check_stack_access()?;
|
||||||
match self.value_stack.pop()? {
|
match self.value_stack.pop()? {
|
||||||
StackValueType::Specific(stack_value_type) => Ok(StackValueType::Specific(stack_value_type)),
|
StackValueType::Specific(stack_value_type) => Ok(StackValueType::Specific(stack_value_type)),
|
||||||
@ -646,20 +646,20 @@ impl<'a> FunctionValidationContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tee_any_value(&mut self) -> Result<StackValueType, Error> {
|
fn tee_any_value(&mut self) -> Result<StackValueType, Error> {
|
||||||
self.check_stack_access()?;
|
self.check_stack_access()?;
|
||||||
Ok(self.value_stack.top().map(Clone::clone)?)
|
Ok(self.value_stack.top().map(Clone::clone)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unreachable(&mut self) -> Result<(), Error> {
|
fn unreachable(&mut self) -> Result<(), Error> {
|
||||||
Ok(self.value_stack.push(StackValueType::AnyUnlimited)?)
|
Ok(self.value_stack.push(StackValueType::AnyUnlimited)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn top_label(&self) -> Result<&BlockFrame, Error> {
|
fn top_label(&self) -> Result<&BlockFrame, Error> {
|
||||||
Ok(self.frame_stack.top()?)
|
Ok(self.frame_stack.top()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_label(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
|
fn push_label(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
|
||||||
Ok(self.frame_stack.push(BlockFrame {
|
Ok(self.frame_stack.push(BlockFrame {
|
||||||
frame_type: frame_type,
|
frame_type: frame_type,
|
||||||
block_type: block_type,
|
block_type: block_type,
|
||||||
@ -670,7 +670,7 @@ impl<'a> FunctionValidationContext<'a> {
|
|||||||
})?)
|
})?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_label(&mut self) -> Result<InstructionOutcome, Error> {
|
fn pop_label(&mut self) -> Result<InstructionOutcome, Error> {
|
||||||
let frame = self.frame_stack.pop()?;
|
let frame = self.frame_stack.pop()?;
|
||||||
let actual_value_type = if self.value_stack.len() > frame.value_stack_len {
|
let actual_value_type = if self.value_stack.len() > frame.value_stack_len {
|
||||||
Some(self.value_stack.pop()?)
|
Some(self.value_stack.pop()?)
|
||||||
@ -694,22 +694,22 @@ impl<'a> FunctionValidationContext<'a> {
|
|||||||
Ok(InstructionOutcome::ValidateNextInstruction)
|
Ok(InstructionOutcome::ValidateNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn require_label(&self, idx: u32) -> Result<&BlockFrame, Error> {
|
fn require_label(&self, idx: u32) -> Result<&BlockFrame, Error> {
|
||||||
Ok(self.frame_stack.get(idx as usize)?)
|
Ok(self.frame_stack.get(idx as usize)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type(&self) -> Result<BlockType, Error> {
|
fn return_type(&self) -> Result<BlockType, Error> {
|
||||||
self.return_type.ok_or(Error("Trying to return from expression".into()))
|
self.return_type.ok_or(Error("Trying to return from expression".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn require_local(&self, idx: u32) -> Result<StackValueType, Error> {
|
fn require_local(&self, idx: u32) -> Result<StackValueType, Error> {
|
||||||
self.locals.get(idx as usize)
|
self.locals.get(idx as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.ok_or(Error(format!("Trying to access local with index {} when there are only {} locals", idx, self.locals.len())))
|
.ok_or(Error(format!("Trying to access local with index {} when there are only {} locals", idx, self.locals.len())))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function_labels(self) -> HashMap<usize, usize> {
|
fn function_labels(self) -> HashMap<usize, usize> {
|
||||||
self.labels
|
self.labels
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,21 +724,21 @@ impl<'a> FunctionValidationContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StackValueType {
|
impl StackValueType {
|
||||||
pub fn is_any(&self) -> bool {
|
fn is_any(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&StackValueType::Any => true,
|
&StackValueType::Any => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_any_unlimited(&self) -> bool {
|
fn is_any_unlimited(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&StackValueType::AnyUnlimited => true,
|
&StackValueType::AnyUnlimited => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_type(&self) -> ValueType {
|
fn value_type(&self) -> ValueType {
|
||||||
match self {
|
match self {
|
||||||
&StackValueType::Any | &StackValueType::AnyUnlimited => unreachable!("must be checked by caller"),
|
&StackValueType::Any | &StackValueType::AnyUnlimited => unreachable!("must be checked by caller"),
|
||||||
&StackValueType::Specific(value_type) => value_type,
|
&StackValueType::Specific(value_type) => value_type,
|
||||||
|
@ -6,7 +6,7 @@ use elements::{BlockType, External, FunctionType, GlobalEntry, GlobalType, Inter
|
|||||||
Module, Opcode, ResizableLimits, TableType, Type, ValueType};
|
Module, Opcode, ResizableLimits, TableType, Type, ValueType};
|
||||||
use common::stack;
|
use common::stack;
|
||||||
use self::context::ModuleContext;
|
use self::context::ModuleContext;
|
||||||
use self::func::{FunctionValidationContext, Validator};
|
use self::func::Validator;
|
||||||
|
|
||||||
pub use self::module::ValidatedModule;
|
pub use self::module::ValidatedModule;
|
||||||
|
|
||||||
|
@ -196,6 +196,40 @@ fn global_init_misc() {
|
|||||||
assert!(validate_module(&m).is_err());
|
assert!(validate_module(&m).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn module_limits_validity() {
|
||||||
|
// module cannot contain more than 1 memory atm.
|
||||||
|
let m = module()
|
||||||
|
.with_import(
|
||||||
|
ImportEntry::new(
|
||||||
|
"core".into(),
|
||||||
|
"memory".into(),
|
||||||
|
External::Memory(MemoryType::new(10, None))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.memory()
|
||||||
|
.with_min(10)
|
||||||
|
.build()
|
||||||
|
.build();
|
||||||
|
assert!(validate_module(&m).is_err());
|
||||||
|
|
||||||
|
// module cannot contain more than 1 table atm.
|
||||||
|
let m = module()
|
||||||
|
.with_import(
|
||||||
|
ImportEntry::new(
|
||||||
|
"core".into(),
|
||||||
|
"table".into(),
|
||||||
|
External::Table(TableType::new(10, None))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.table()
|
||||||
|
.with_min(10)
|
||||||
|
.build()
|
||||||
|
.build();
|
||||||
|
assert!(validate_module(&m).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: pepyakin
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn if_else_with_return_type_validation() {
|
// fn if_else_with_return_type_validation() {
|
||||||
// let module_instance = ModuleInstance::new(Weak::default(), "test".into(), module().build()).unwrap();
|
// let module_instance = ModuleInstance::new(Weak::default(), "test".into(), module().build()).unwrap();
|
||||||
|
Reference in New Issue
Block a user