Skip to content

Commit

Permalink
Merge pull request #15 from ElrondNetwork/memorygrow-limit
Browse files Browse the repository at this point in the history
Add memory.grow runtime limit and refactor OpcodeControl
  • Loading branch information
camilbancioiu authored Nov 9, 2021
2 parents 233c950 + 09c6265 commit 2549b5a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 14 deletions.
67 changes: 54 additions & 13 deletions lib/middleware-common/src/opcode_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,65 @@ use wasmer_runtime_core::{

use crate::runtime_breakpoints::{push_runtime_breakpoint, BREAKPOINT_VALUE_EXECUTION_FAILED};

static FIELD_MEMORY_GROW_COUNT: InternalField = InternalField::allocate();

static FIELD_OPERAND_BACKUP: InternalField = InternalField::allocate();

pub struct OpcodeControl {
pub max_memory_grow: usize,
pub max_memory_grow_delta: usize,
}

impl OpcodeControl {
pub fn new(max_memory_grow_delta: usize) -> OpcodeControl {
pub fn new(max_memory_grow: usize, max_memory_grow_delta: usize) -> OpcodeControl {
OpcodeControl {
max_memory_grow,
max_memory_grow_delta,
}
}

fn inject_memory_grow_count_limit(&mut self, sink: &mut EventSink) {
sink.push(Event::Internal(InternalEvent::GetInternal(
FIELD_MEMORY_GROW_COUNT.index() as _,
)));
sink.push(Event::WasmOwned(Operator::I64Const {
value: self.max_memory_grow as i64,
}));
sink.push(Event::WasmOwned(Operator::I64GeU));
sink.push(Event::WasmOwned(Operator::If {
ty: WpTypeOrFuncType::Type(WpType::EmptyBlockType),
}));
push_runtime_breakpoint(sink, BREAKPOINT_VALUE_EXECUTION_FAILED);
sink.push(Event::WasmOwned(Operator::End));
}

fn inject_memory_grow_count_increment(&mut self, sink: &mut EventSink) {
sink.push(Event::Internal(InternalEvent::GetInternal(
FIELD_MEMORY_GROW_COUNT.index() as _,
)));
sink.push(Event::WasmOwned(Operator::I64Const{
value: 1 as i64,
}));
sink.push(Event::WasmOwned(Operator::I64Add));
sink.push(Event::Internal(InternalEvent::SetInternal(
FIELD_MEMORY_GROW_COUNT.index() as _,
)));
}

fn inject_memory_grow_delta_limit(&mut self, sink: &mut EventSink) {
sink.push(Event::Internal(InternalEvent::GetInternal(
FIELD_OPERAND_BACKUP.index() as _,
)));
sink.push(Event::WasmOwned(Operator::I64Const {
value: self.max_memory_grow_delta as i64,
}));
sink.push(Event::WasmOwned(Operator::I64GtU));
sink.push(Event::WasmOwned(Operator::If {
ty: WpTypeOrFuncType::Type(WpType::EmptyBlockType),
}));
push_runtime_breakpoint(sink, BREAKPOINT_VALUE_EXECUTION_FAILED);
sink.push(Event::WasmOwned(Operator::End));
}
}

impl FunctionMiddleware for OpcodeControl {
Expand All @@ -38,6 +85,11 @@ impl FunctionMiddleware for OpcodeControl {
return Err("MemoryGrow must have memory index 0".to_string());
}

// Before attempting anything with memory.grow, the current memory.grow
// count is checked against the self.max_memory_grow limit.
self.inject_memory_grow_count_limit(sink);
self.inject_memory_grow_count_increment(sink);

// Backup the top of the stack (the parameter for memory.grow) in order to
// duplicate it: once for the comparison against max_memory_grow_delta and
// again for memory.grow itself, assuming the comparison passes.
Expand All @@ -46,18 +98,7 @@ impl FunctionMiddleware for OpcodeControl {
)));

// Set up the comparison against max_memory_grow_delta.
sink.push(Event::Internal(InternalEvent::GetInternal(
FIELD_OPERAND_BACKUP.index() as _,
)));
sink.push(Event::WasmOwned(Operator::I32Const {
value: self.max_memory_grow_delta as i32,
}));
sink.push(Event::WasmOwned(Operator::I32GtU));
sink.push(Event::WasmOwned(Operator::If {
ty: WpTypeOrFuncType::Type(WpType::EmptyBlockType),
}));
push_runtime_breakpoint(sink, BREAKPOINT_VALUE_EXECUTION_FAILED);
sink.push(Event::WasmOwned(Operator::End));
self.inject_memory_grow_delta_limit(sink);

// Bring back the backed-up operand for memory.grow.
sink.push(Event::Internal(InternalEvent::GetInternal(
Expand Down
6 changes: 5 additions & 1 deletion lib/runtime-c-api/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ pub struct wasmer_compilation_options_t;
pub struct CompilationOptions {
pub gas_limit: u64,
pub unmetered_locals: usize,
pub max_memory_grow: usize,
pub max_memory_grow_delta: usize,
pub opcode_trace: bool,
pub metering: bool,
Expand Down Expand Up @@ -266,7 +267,10 @@ pub unsafe fn prepare_middleware_chain_generator(
));
}

chain.push(opcode_control::OpcodeControl::new(options.max_memory_grow_delta));
chain.push(opcode_control::OpcodeControl::new(
options.max_memory_grow,
options.max_memory_grow_delta
));

// The RuntimeBreakpointHandler must be the last middleware in the chain (OpcodeTracer is
// an exception since it does not alter the opcodes meaningfully.
Expand Down

0 comments on commit 2549b5a

Please sign in to comment.