Skip to content

Commit

Permalink
Merge tag 'v1.5.1' into feat/bump_1.5.1
Browse files Browse the repository at this point in the history
  • Loading branch information
da1suk8 committed Feb 5, 2024
2 parents 51a1820 + e2ad213 commit 602dab3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 9 deletions.
16 changes: 16 additions & 0 deletions packages/vm/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,22 @@ pub struct CacheOptions {
pub instance_memory_limit: Size,
}

impl CacheOptions {
pub fn new(
base_dir: impl Into<PathBuf>,
available_capabilities: impl Into<HashSet<String>>,
memory_cache_size: Size,
instance_memory_limit: Size,
) -> Self {
Self {
base_dir: base_dir.into(),
available_capabilities: available_capabilities.into(),
memory_cache_size,
instance_memory_limit,
}
}
}

pub struct CacheInner {
/// The directory in which the Wasm blobs are stored in the file system.
wasm_path: PathBuf,
Expand Down
26 changes: 26 additions & 0 deletions packages/vm/src/compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ const TABLE_SIZE_LIMIT: u32 = 2500; // entries
/// when a user accidentally includes wasm-bindgen, they get a bunch of unsupported imports.
const MAX_IMPORTS: usize = 100;

const MAX_FUNCTIONS: usize = 10000;

const MAX_FUNCTION_PARAMS: usize = 50;

const MAX_FUNCTION_RESULTS: usize = 1;

/// Checks if the data is valid wasm and compatibility with the CosmWasm API (imports and exports)
pub fn check_wasm(wasm_code: &[u8], available_capabilities: &HashSet<String>) -> VmResult<()> {
let module = ParsedWasm::parse(wasm_code)?;
Expand All @@ -88,6 +94,7 @@ pub fn check_wasm(wasm_code: &[u8], available_capabilities: &HashSet<String>) ->
check_wasm_exports(&module)?;
check_wasm_imports(&module, SUPPORTED_IMPORTS)?;
check_wasm_capabilities(&module, available_capabilities)?;
check_wasm_functions(&module)?;

Ok(())
}
Expand Down Expand Up @@ -235,6 +242,25 @@ fn check_wasm_capabilities(
Ok(())
}

fn check_wasm_functions(module: &ParsedWasm) -> VmResult<()> {
if module.function_count > MAX_FUNCTIONS {
return Err(VmError::static_validation_err(format!(
"Wasm contract contains more than {MAX_FUNCTIONS} functions"
)));
}
if module.max_func_params > MAX_FUNCTION_PARAMS {
return Err(VmError::static_validation_err(format!(
"Wasm contract contains function with more than {MAX_FUNCTION_PARAMS} parameters"
)));
}
if module.max_func_results > MAX_FUNCTION_RESULTS {
return Err(VmError::static_validation_err(format!(
"Wasm contract contains function with more than {MAX_FUNCTION_RESULTS} results"
)));
}
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
10 changes: 7 additions & 3 deletions packages/vm/src/modules/file_system_cache.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::fs;
use std::hash::Hash;
use std::io;
use std::panic::catch_unwind;
use std::path::{Path, PathBuf};
use thiserror::Error;

Expand Down Expand Up @@ -166,9 +167,12 @@ impl FileSystemCache {
.map_err(|_e| VmError::cache_err("Error creating modules directory"))?;

let path = self.module_file(checksum);
module
.serialize_to_file(&path)
.map_err(|e| VmError::cache_err(format!("Error writing module to disk: {e}")))?;
catch_unwind(|| {
module
.serialize_to_file(&path)
.map_err(|e| VmError::cache_err(format!("Error writing module to disk: {e}")))
})
.map_err(|_| VmError::cache_err("Could not write module to disk"))??;
let module_size = module_size(&path)?;
Ok(module_size)
}
Expand Down
37 changes: 31 additions & 6 deletions packages/vm/src/parsed_wasm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use wasmer::wasmparser::{
Export, Import, MemoryType, Parser, TableType, ValidPayload, Validator, WasmFeatures,
Export, Import, MemoryType, Parser, Payload, TableType, Type, ValidPayload, Validator,
WasmFeatures,
};

use crate::VmResult;
Expand All @@ -13,6 +14,10 @@ pub struct ParsedWasm<'a> {
pub imports: Vec<Import<'a>>,
pub tables: Vec<TableType>,
pub memories: Vec<MemoryType>,
pub function_count: usize,
pub type_count: u32,
pub max_func_params: usize,
pub max_func_results: usize,
}

impl<'a> ParsedWasm<'a> {
Expand All @@ -34,6 +39,10 @@ impl<'a> ParsedWasm<'a> {
imports: vec![],
tables: vec![],
memories: vec![],
function_count: 0,
type_count: 0,
max_func_params: 0,
max_func_results: 0,
};

let mut fun_allocations = Default::default();
Expand All @@ -45,20 +54,36 @@ impl<'a> ParsedWasm<'a> {
let mut fun_validator = fv.into_validator(fun_allocations);
fun_validator.validate(&body)?;
fun_allocations = fun_validator.into_allocations();

this.function_count += 1;
}

match p {
wasmer::wasmparser::Payload::Version { num, .. } => this.version = num,
wasmer::wasmparser::Payload::ImportSection(i) => {
Payload::TypeSection(t) => {
this.type_count = t.get_count();
for t_res in t {
let ty: Type = t_res?;
match ty {
Type::Func(ft) => {
this.max_func_params =
core::cmp::max(ft.params().len(), this.max_func_params);
this.max_func_results =
core::cmp::max(ft.results().len(), this.max_func_results);
}
}
}
}
Payload::Version { num, .. } => this.version = num,
Payload::ImportSection(i) => {
this.imports = i.into_iter().collect::<Result<Vec<_>, _>>()?;
}
wasmer::wasmparser::Payload::TableSection(t) => {
Payload::TableSection(t) => {
this.tables = t.into_iter().collect::<Result<Vec<_>, _>>()?;
}
wasmer::wasmparser::Payload::MemorySection(m) => {
Payload::MemorySection(m) => {
this.memories = m.into_iter().collect::<Result<Vec<_>, _>>()?;
}
wasmer::wasmparser::Payload::ExportSection(e) => {
Payload::ExportSection(e) => {
this.exports = e.into_iter().collect::<Result<Vec<_>, _>>()?;
}
_ => {} // ignore everything else
Expand Down

0 comments on commit 602dab3

Please sign in to comment.