Skip to content

Commit

Permalink
feat: limit the regions length using dynamic link
Browse files Browse the repository at this point in the history
  • Loading branch information
loloicci committed Sep 2, 2022
1 parent d601ee1 commit 0e0ec95
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 3 deletions.
52 changes: 49 additions & 3 deletions packages/vm/src/dynamic_link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ use std::str;
use crate::backend::{BackendApi, Querier, Storage};
use crate::conversion::{ref_to_u32, to_u32};
use crate::environment::{process_gas_info, Environment};
use crate::errors::{CommunicationError, VmResult};
use crate::errors::{CommunicationError, VmError, VmResult};
use crate::memory::{read_region, write_region};
use wasmer::{Exports, Function, FunctionType, ImportObject, Module, RuntimeError, Val};
use wasmer_types::ImportIndex;

const MAX_REGIONS_LENGTH: usize = 100_000;

pub type WasmerVal = Val;

pub struct FunctionMetadata {
Expand Down Expand Up @@ -191,9 +193,24 @@ where
Q2: Querier + 'static,
{
let mut copied_region_ptrs = Vec::<WasmerVal>::with_capacity(vals.len());
let mut max_regions_len = MAX_REGIONS_LENGTH;
for val in vals {
let val_region_ptr = ref_to_u32(val)?;
let data = read_region(&src_env.memory(), val_region_ptr, u32::MAX as usize)?;
let data = read_region(&src_env.memory(), val_region_ptr, max_regions_len).map_err(
|e| match e {
VmError::CommunicationErr {
source: CommunicationError::RegionLengthTooBig { .. },
#[cfg(feature = "backtraces")]
backtrace,
} => VmError::CommunicationErr {
source: CommunicationError::exceeds_limit_of_copy_region(MAX_REGIONS_LENGTH),
#[cfg(feature = "backtraces")]
backtrace,
},
_ => e,
},
)?;
max_regions_len -= data.len();
if deallocation {
src_env.call_function0("deallocate", &[val_region_ptr.into()])?;
}
Expand Down Expand Up @@ -223,7 +240,6 @@ mod tests {
MockQuerier, MockStorage, INSTANCE_CACHE,
};
use crate::to_vec;
use crate::VmError;

static CONTRACT: &[u8] = include_bytes!("../testdata/hackatom.wasm");

Expand Down Expand Up @@ -315,6 +331,36 @@ mod tests {
));
}

#[test]
fn trying_copy_too_large_region_fails() {
let src_instance = mock_instance(&CONTRACT, &[]);
let dst_instance = mock_instance(&CONTRACT, &[]);

let big_data_1 = [0_u8; MAX_REGIONS_LENGTH - 42 + 1];
let big_data_2 = [1_u8; 42];

let data_ptr1 = write_data_to_mock_env(&src_instance.env, &big_data_1).unwrap();
let data_ptr2 = write_data_to_mock_env(&src_instance.env, &big_data_2).unwrap();
let copy_result = copy_region_vals_between_env(
&src_instance.env,
&dst_instance.env,
&[
WasmerVal::I32(data_ptr1 as i32),
WasmerVal::I32(data_ptr2 as i32),
],
true,
);
assert!(matches!(
copy_result.unwrap_err(),
VmError::CommunicationErr {
source: CommunicationError::ExceedsLimitOfCopyRegion {
max_length: MAX_REGIONS_LENGTH
},
..
}
))
}

fn init_cache_with_two_instances() {
let callee_wasm = wat::parse_str(
r#"(module
Expand Down
17 changes: 17 additions & 0 deletions packages/vm/src/errors/communication_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub enum CommunicationError {
RegionLengthTooBig { length: usize, max_length: usize },
#[error("Region too small. Got {}, required {}", size, required)]
RegionTooSmall { size: usize, required: usize },
#[error("Regions length too big. limit {}", max_length)]
ExceedsLimitOfCopyRegion { max_length: usize },
#[error("Got a zero Wasm address")]
ZeroAddress {},
}
Expand Down Expand Up @@ -64,6 +66,10 @@ impl CommunicationError {
CommunicationError::RegionTooSmall { size, required }
}

pub(crate) fn exceeds_limit_of_copy_region(max_length: usize) -> Self {
CommunicationError::ExceedsLimitOfCopyRegion { max_length }
}

pub(crate) fn zero_address() -> Self {
CommunicationError::ZeroAddress {}
}
Expand Down Expand Up @@ -131,6 +137,17 @@ mod tests {
}
}

#[test]
fn exceeds_limit_of_copy_region_works() {
let error = CommunicationError::exceeds_limit_of_copy_region(42);
match error {
CommunicationError::ExceedsLimitOfCopyRegion { max_length, .. } => {
assert_eq!(max_length, 42);
}
e => panic!("Unexpected error: {:?}", e),
}
}

#[test]
fn zero_address() {
let error = CommunicationError::zero_address();
Expand Down

0 comments on commit 0e0ec95

Please sign in to comment.