Skip to content

Commit

Permalink
Add a small harness that just loads all wasms from a workspace direct…
Browse files Browse the repository at this point in the history
…ory (#1454)

This is just a small test harness to help people who want to run simple
testcases they've generated outside soroban. Put your wasm file in
`soroban-env-host/src/test/hostile_inputs` and run `cargo test
test_misc_hostile_wasms` and it should just pick your wasm up and
attempt to instantiate and run it.

Requirements:

- The wasm has to have the normal contract metadata section on the
front! Absent that it will be rejected immediately.
- The wasm of course has to comply with the limited profile soroban uses
(few-if-any post-MVP features, no floating point, etc.)
- The wasm has to expose a 0-arg function called "test" which is the
only thing the test tries to execute.
  • Loading branch information
graydon authored Sep 6, 2024
1 parent df18803 commit a79b3cf
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: rustup update
- uses: stellar/binaries@v24
- uses: stellar/binaries@v29
with:
name: cargo-semver-checks
version: 0.32.0
version: 0.35.0
- run: cargo semver-checks --exclude soroban-simulation

build-and-test:
Expand Down
101 changes: 101 additions & 0 deletions soroban-env-host/src/test/hostile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1322,3 +1322,104 @@ fn test_stack_depth_stability() {
(ScErrorType::Budget, ScErrorCode::ExceededLimit)
));
}

#[test]
fn test_misc_hostile_wasms() {
// This test loads and runs a bunch of hostile WASM modules
// found in the hostile_inputs subdirectory. It attempts to
// instantiate the contract and then run a 0-ary function in
// the contract called "test".
let mut bad_inputs = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
bad_inputs.push("src/test/hostile_inputs");
eprintln!("loading hostile inputs from {:?}", bad_inputs);
let mut n_wasms = 0;
let mut n_instantiated_ok = 0;
let mut n_instantiated_external_error = 0;
let mut n_instantiated_internal_error = 0;
let mut n_executed_ok = 0;
let mut n_executed_external_error = 0;
let mut n_executed_internal_error = 0;

for entry in std::fs::read_dir(bad_inputs).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
if path.extension().unwrap() == "wasm" {
let host = Host::test_host_with_recording_footprint();
let filename = path.file_name().unwrap().to_str().unwrap().to_string();
let wasm_code = std::fs::read(path).unwrap();
eprintln!("loaded {}-byte wasm {}", wasm_code.len(), filename);
n_wasms += 1;
host.as_budget().reset_unlimited().unwrap();
let addr_res = host.register_test_contract_wasm_from_source_account(
&wasm_code,
generate_account_id(&host),
generate_bytes_array(&host),
);
match addr_res {
Err(e) => {
if e.error.is_code(ScErrorCode::InternalError) {
eprintln!(
"instantiation failed with internal error for {}: {:?}",
filename, e
);
n_instantiated_internal_error += 1;
} else {
eprintln!(
"instantiation failed with external error for {}: {:?}",
filename, e
);
n_instantiated_external_error += 1;
}
continue;
}
Ok(contract_id) => {
n_instantiated_ok += 1;
let call_res = host.call(
contract_id,
Symbol::try_from_small_str("test").unwrap(),
test_vec![&host].into(),
);
if let Err(e) = call_res {
if e.error.is_code(ScErrorCode::InternalError) {
eprintln!(
"execution failed with internal error for {}: {:?}",
filename, e
);
n_executed_internal_error += 1;
} else {
eprintln!(
"execution failed with external error for {}: {:?}",
filename, e
);
n_executed_external_error += 1;
}
} else {
n_executed_ok += 1;
eprintln!("execution succeeded for {}", filename);
}
}
}
}
}
eprintln!("loaded {} hostile Wasm modules", n_wasms);
eprintln!("instantiated {} contracts successfully", n_instantiated_ok);
eprintln!(
"instantiation failed with external error for {} contracts",
n_instantiated_external_error
);
eprintln!(
"instantiation failed with internal error for {} contracts",
n_instantiated_internal_error
);
eprintln!("executed {} contracts successfully", n_executed_ok);
eprintln!(
"execution failed with external error for {} contracts",
n_executed_external_error
);
eprintln!(
"execution failed with internal error for {} contracts",
n_executed_internal_error
);
assert_eq!(n_instantiated_internal_error, 0);
assert_eq!(n_executed_internal_error, 0);
}
Binary file not shown.
Binary file added soroban-env-host/src/test/hostile_inputs/smoke.wasm
Binary file not shown.

0 comments on commit a79b3cf

Please sign in to comment.