Skip to content

Commit

Permalink
Merge #323
Browse files Browse the repository at this point in the history
323: add validate subcommand r=MarkMcCaskey a=MarkMcCaskey



Co-authored-by: Mark McCaskey <mark@wasmer.io>
Co-authored-by: Mark McCaskey <markmccaskey@users.noreply.github.com>
  • Loading branch information
3 people committed Apr 4, 2019
2 parents b06b9ec + 03b529d commit 1ac689c
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 6 deletions.
8 changes: 7 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/runtime-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ edition = "2018"
[dependencies]
nix = "0.12.0"
page_size = "0.4.1"
wasmparser = "0.23.0"
wasmparser = "0.29.2"
parking_lot = "0.7.1"
lazy_static = "1.2.0"
indexmap = "1.0.2"
Expand Down
9 changes: 7 additions & 2 deletions lib/runtime-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,18 @@ pub fn compile_with_config(
/// WebAssembly specification. Returns `true` if validation
/// succeeded, `false` if validation failed.
pub fn validate(wasm: &[u8]) -> bool {
validate_and_report_errors(wasm).is_ok()
}

/// The same as `validate` but with an Error message on failure
pub fn validate_and_report_errors(wasm: &[u8]) -> ::std::result::Result<(), String> {
use wasmparser::WasmDecoder;
let mut parser = wasmparser::ValidatingParser::new(wasm, None);
loop {
let state = parser.read();
match *state {
wasmparser::ParserState::EndWasm => break true,
wasmparser::ParserState::Error(_) => break false,
wasmparser::ParserState::EndWasm => break Ok(()),
wasmparser::ParserState::Error(e) => break Err(format!("{}", e)),
_ => {}
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/runtime-core/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl ModuleInfo {
let len = reader.bytes_remaining();
let bytes = reader.read_bytes(len)?;
let data = bytes.to_vec();
let name = String::from_utf8_lossy(name).to_string();
let name = name.to_string();
self.custom_sections.insert(name, data);
}
}
Expand Down
52 changes: 51 additions & 1 deletion src/bin/wasmer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use structopt::StructOpt;
use wasmer::webassembly::InstanceABI;
use wasmer::*;
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH};
use wasmer_runtime_core::backend::CompilerConfig;
use wasmer_runtime_core::{self, backend::CompilerConfig};
#[cfg(feature = "wasi")]
use wasmer_wasi;

Expand All @@ -29,6 +29,10 @@ enum CLIOptions {
#[structopt(name = "cache")]
Cache(Cache),

/// Validate a Web Assembly binary
#[structopt(name = "validate")]
Validate(Validate),

/// Update wasmer to the latest version
#[structopt(name = "self-update")]
SelfUpdate,
Expand Down Expand Up @@ -64,6 +68,13 @@ enum Cache {
Dir,
}

#[derive(Debug, StructOpt)]
struct Validate {
/// Input file
#[structopt(parse(from_os_str))]
path: PathBuf,
}

/// Read the contents of a file
fn read_file_contents(path: &PathBuf) -> Result<Vec<u8>, io::Error> {
let mut buffer: Vec<u8> = Vec::new();
Expand Down Expand Up @@ -267,6 +278,42 @@ fn run(options: Run) {
}
}

fn validate_wasm(validate: Validate) -> Result<(), String> {
let wasm_path = validate.path;
let wasm_path_as_str = wasm_path.to_str().unwrap();

let wasm_binary: Vec<u8> = read_file_contents(&wasm_path).map_err(|err| {
format!(
"Can't read the file {}: {}",
wasm_path.as_os_str().to_string_lossy(),
err
)
})?;

if !utils::is_wasm_binary(&wasm_binary) {
return Err(format!(
"Cannot recognize \"{}\" as a WASM binary",
wasm_path_as_str,
));
}

wasmer_runtime_core::validate_and_report_errors(&wasm_binary)
.map_err(|err| format!("Validation failed: {}", err))?;

Ok(())
}

/// Runs logic for the `validate` subcommand
fn validate(validate: Validate) {
match validate_wasm(validate) {
Err(message) => {
eprintln!("Error: {}", message);
exit(-1);
}
_ => (),
}
}

fn main() {
let options = CLIOptions::from_args();
match options {
Expand All @@ -291,6 +338,9 @@ fn main() {
println!("{}", get_cache_dir().to_string_lossy());
}
},
CLIOptions::Validate(validate_options) => {
validate(validate_options);
}
#[cfg(target_os = "windows")]
CLIOptions::Cache(_) => {
println!("Caching is disabled for Windows.");
Expand Down

0 comments on commit 1ac689c

Please sign in to comment.