Skip to content

Commit

Permalink
Add doc comments and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
chipshort committed Jul 17, 2024
1 parent 4308226 commit a6a53f5
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
70 changes: 70 additions & 0 deletions packages/vm/src/compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,23 @@ 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;

/// The maximum number of functions a contract can have.
/// Any contract with more functions than this will be rejected during static validation.
const MAX_FUNCTIONS: usize = 20_000;

/// The maximum number of parameters a wasm function can have.
/// Any contract with a function type with more parameters than this will be rejected
/// during static validation.
const MAX_FUNCTION_PARAMS: usize = 100;

/// The maximum total number of parameters of all functions in the wasm.
/// For each function in the wasm, take the number of parameters and sum all of these up.
/// If that sum exceeds this limit, the wasm will be rejected during static validation.
const MAX_TOTAL_FUNCTION_PARAMS: usize = 10_000;

/// The maximum number of results a wasm function can have.
/// Any contract with a function type with more results than this will be rejected
/// during static validation.
const MAX_FUNCTION_RESULTS: usize = 1;

/// Checks if the data is valid wasm and compatibility with the CosmWasm API (imports and exports)
Expand Down Expand Up @@ -935,4 +946,63 @@ mod tests {
_ => panic!("Got unexpected error"),
}
}

#[test]
fn check_wasm_fails_for_big_functions() {
// too many arguments
let args = " i32".repeat(MAX_FUNCTION_PARAMS + 1);
let wasm = wat::parse_str(format!(
r#"(module
(type (func (param {args})))
(func (type 0) nop)
)"#
))
.unwrap();
let module = ParsedWasm::parse(&wasm).unwrap();

match check_wasm_functions(&module).unwrap_err() {
VmError::StaticValidationErr { msg, .. } => assert_eq!(
msg,
"Wasm contract contains function with more than 100 parameters"
),
_ => panic!("Got unexpected error"),
}

// too many returns
let return_types = " i32".repeat(MAX_FUNCTION_RESULTS + 1);
let returns = " i32.const 42".repeat(MAX_FUNCTION_RESULTS + 1);
let wasm = wat::parse_str(format!(
r#"(module
(type (func (result {return_types})))
(func (type 0) {returns})
)"#
))
.unwrap();
let module = ParsedWasm::parse(&wasm).unwrap();
match check_wasm_functions(&module).unwrap_err() {
VmError::StaticValidationErr { msg, .. } => assert_eq!(
msg,
"Wasm contract contains function with more than 1 results"
),
_ => panic!("Got unexpected error"),
}

// too many functions
let functions = ["(func (type 0) nop)"; MAX_FUNCTIONS + 1];
let functions = functions.join("\n");
let wasm = wat::parse_str(format!(
r#"(module
(type (func))
{functions}
)"#
))
.unwrap();
let module = ParsedWasm::parse(&wasm).unwrap();
match check_wasm_functions(&module).unwrap_err() {
VmError::StaticValidationErr { msg, .. } => {
assert_eq!(msg, "Wasm contract contains more than 20000 functions")
}
_ => panic!("Got unexpected error"),
}
}
}
41 changes: 41 additions & 0 deletions packages/vm/src/parsed_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,45 @@ mod test {
.unwrap();
assert!(ParsedWasm::parse(&wasm_data).is_err());
}

#[test]
fn parsed_wasm_counts_functions_correctly() {
let wasm = wat::parse_str(r#"(module)"#).unwrap();
let module = ParsedWasm::parse(&wasm).unwrap();
assert_eq!(module.function_count, 0);

let wasm = wat::parse_str(
r#"(module
(type (func))
(func (type 0) nop)
(func (type 0) nop)
(export "foo" (func 0))
(export "bar" (func 0))
)"#,
)
.unwrap();
let module = ParsedWasm::parse(&wasm).unwrap();
assert_eq!(module.function_count, 2);
}

#[test]
fn parsed_wasm_counts_func_io_correctly() {
let wasm = wat::parse_str(r#"(module)"#).unwrap();
let module = ParsedWasm::parse(&wasm).unwrap();
assert_eq!(module.max_func_params, 0);
assert_eq!(module.max_func_results, 0);

let wasm = wat::parse_str(
r#"(module
(type (func (param i32 i32 i32) (result i32)))
(type (func (param i32) (result i32 i32)))
(func (type 1) i32.const 42 i32.const 42)
(func (type 0) i32.const 42)
)"#,
)
.unwrap();
let module = ParsedWasm::parse(&wasm).unwrap();
assert_eq!(module.max_func_params, 3);
assert_eq!(module.max_func_results, 2);
}
}

0 comments on commit a6a53f5

Please sign in to comment.