Better error handling in fuzzing; skip on unsupported features
This commit is contained in:
parent
88bcc3d906
commit
26e7c7a3af
|
@ -1,12 +1,28 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use waffle::Module;
|
use waffle::{FrontendError, Module};
|
||||||
|
|
||||||
fuzz_target!(|module: wasm_smith::Module| {
|
fuzz_target!(|module: wasm_smith::Module| {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
log::debug!("original module: {:?}", module);
|
log::debug!("original module: {:?}", module);
|
||||||
let orig_bytes = module.to_bytes();
|
let orig_bytes = module.to_bytes();
|
||||||
let parsed_module = Module::from_wasm_bytes(&orig_bytes[..]).unwrap();
|
let parsed_module = match Module::from_wasm_bytes(&orig_bytes[..]) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(e) => {
|
||||||
|
match e.downcast::<FrontendError>() {
|
||||||
|
Ok(FrontendError::UnsupportedFeature(_)) => {
|
||||||
|
// Just skip this case.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ok(e) => {
|
||||||
|
panic!("Frontend error: {:?}", e);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
panic!("Other error when parsing module: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
let _ = parsed_module.to_wasm_bytes();
|
let _ = parsed_module.to_wasm_bytes();
|
||||||
});
|
});
|
||||||
|
|
15
src/errors.rs
Normal file
15
src/errors.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//! Error types.
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum FrontendError {
|
||||||
|
UnsupportedFeature(String),
|
||||||
|
Internal(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for FrontendError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
std::fmt::Debug::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for FrontendError {}
|
|
@ -3,6 +3,7 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use crate::entity::EntityRef;
|
use crate::entity::EntityRef;
|
||||||
|
use crate::errors::FrontendError;
|
||||||
use crate::ir::*;
|
use crate::ir::*;
|
||||||
use crate::op_traits::{op_inputs, op_outputs};
|
use crate::op_traits::{op_inputs, op_outputs};
|
||||||
use crate::ops::Operator;
|
use crate::ops::Operator;
|
||||||
|
@ -33,17 +34,20 @@ fn parse_init_expr<'a>(init_expr: &wasmparser::ConstExpr<'a>) -> Result<Option<u
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
if operators.len() != 2 || !matches!(&operators[1], &wasmparser::Operator::End) {
|
if operators.len() != 2 || !matches!(&operators[1], &wasmparser::Operator::End) {
|
||||||
anyhow::bail!(
|
bail!(FrontendError::UnsupportedFeature(format!(
|
||||||
"Unsupported operator seq in base-address expr: {:?}",
|
"Unsupported operator seq in base-address expr: {:?}",
|
||||||
operators
|
operators
|
||||||
);
|
)));
|
||||||
}
|
}
|
||||||
Ok(match &operators[0] {
|
Ok(match &operators[0] {
|
||||||
&wasmparser::Operator::I32Const { value } => Some(value as u64),
|
&wasmparser::Operator::I32Const { value } => Some(value as u64),
|
||||||
&wasmparser::Operator::I64Const { value } => Some(value as u64),
|
&wasmparser::Operator::I64Const { value } => Some(value as u64),
|
||||||
&wasmparser::Operator::F32Const { value } => Some(value.bits() as u64),
|
&wasmparser::Operator::F32Const { value } => Some(value.bits() as u64),
|
||||||
&wasmparser::Operator::F64Const { value } => Some(value.bits()),
|
&wasmparser::Operator::F64Const { value } => Some(value.bits()),
|
||||||
op => anyhow::bail!("Unsupported data segment base-address operator: {:?}", op),
|
op => anyhow::bail!(FrontendError::UnsupportedFeature(format!(
|
||||||
|
"Unsupported data segment base-address operator: {:?}",
|
||||||
|
op
|
||||||
|
))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +190,10 @@ fn handle_payload<'a>(
|
||||||
for element in reader {
|
for element in reader {
|
||||||
let element = element?;
|
let element = element?;
|
||||||
if element.ty != wasmparser::ValType::FuncRef {
|
if element.ty != wasmparser::ValType::FuncRef {
|
||||||
anyhow::bail!("Unsupported table type: {:?}", element.ty);
|
bail!(FrontendError::UnsupportedFeature(format!(
|
||||||
|
"Unsupported table type: {:?}",
|
||||||
|
element.ty
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
match &element.kind {
|
match &element.kind {
|
||||||
wasmparser::ElementKind::Passive => {}
|
wasmparser::ElementKind::Passive => {}
|
||||||
|
@ -206,7 +213,10 @@ fn handle_payload<'a>(
|
||||||
for item in items {
|
for item in items {
|
||||||
let func = match item {
|
let func = match item {
|
||||||
wasmparser::ElementItem::Func(func_idx) => Func::from(func_idx),
|
wasmparser::ElementItem::Func(func_idx) => Func::from(func_idx),
|
||||||
_ => anyhow::bail!("Unsupported element item: {:?}", item),
|
_ => bail!(FrontendError::UnsupportedFeature(format!(
|
||||||
|
"Unsupported element item: {:?}",
|
||||||
|
item
|
||||||
|
))),
|
||||||
};
|
};
|
||||||
funcs.push(func);
|
funcs.push(func);
|
||||||
}
|
}
|
||||||
|
@ -1099,7 +1109,9 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
self.cur_block = Some(el);
|
self.cur_block = Some(el);
|
||||||
self.locals.start_block(el);
|
self.locals.start_block(el);
|
||||||
} else {
|
} else {
|
||||||
bail!("Else without If on top of frame stack");
|
bail!(FrontendError::Internal(format!(
|
||||||
|
"Else without If on top of frame stack"
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,7 +1175,10 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
|
||||||
self.emit_ret(&retvals[..]);
|
self.emit_ret(&retvals[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => bail!("Unsupported operator: {:?}", op),
|
_ => bail!(FrontendError::UnsupportedFeature(format!(
|
||||||
|
"Unsupported operator: {:?}",
|
||||||
|
op
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -14,6 +14,8 @@ mod op_traits;
|
||||||
mod ops;
|
mod ops;
|
||||||
pub mod passes;
|
pub mod passes;
|
||||||
mod scoped_map;
|
mod scoped_map;
|
||||||
|
mod errors;
|
||||||
|
|
||||||
pub use ir::*;
|
pub use ir::*;
|
||||||
pub use ops::{Ieee32, Ieee64, Operator};
|
pub use ops::{Ieee32, Ieee64, Operator};
|
||||||
|
pub use errors::*;
|
||||||
|
|
Loading…
Reference in a new issue