From 26e7c7a3af54fab6bbcce8eb490d46a3c9def97d Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Tue, 29 Nov 2022 10:05:43 -0800 Subject: [PATCH] Better error handling in fuzzing; skip on unsupported features --- fuzz/fuzz_targets/roundtrip.rs | 20 ++++++++++++++++++-- src/errors.rs | 15 +++++++++++++++ src/frontend.rs | 29 ++++++++++++++++++++++------- src/lib.rs | 2 ++ 4 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 src/errors.rs diff --git a/fuzz/fuzz_targets/roundtrip.rs b/fuzz/fuzz_targets/roundtrip.rs index f5e7ad9..f9cddbc 100644 --- a/fuzz/fuzz_targets/roundtrip.rs +++ b/fuzz/fuzz_targets/roundtrip.rs @@ -1,12 +1,28 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use waffle::Module; +use waffle::{FrontendError, Module}; fuzz_target!(|module: wasm_smith::Module| { let _ = env_logger::try_init(); log::debug!("original module: {:?}", module); 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::() { + 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(); }); diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..c325db3 --- /dev/null +++ b/src/errors.rs @@ -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 {} diff --git a/src/frontend.rs b/src/frontend.rs index 6f33159..685ac6e 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -3,6 +3,7 @@ #![allow(dead_code)] use crate::entity::EntityRef; +use crate::errors::FrontendError; use crate::ir::*; use crate::op_traits::{op_inputs, op_outputs}; use crate::ops::Operator; @@ -33,17 +34,20 @@ fn parse_init_expr<'a>(init_expr: &wasmparser::ConstExpr<'a>) -> Result Some(value as u64), &wasmparser::Operator::I64Const { value } => Some(value as u64), &wasmparser::Operator::F32Const { value } => Some(value.bits() as u64), &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 { let element = element?; 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 { wasmparser::ElementKind::Passive => {} @@ -206,7 +213,10 @@ fn handle_payload<'a>( for item in items { let func = match item { 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); } @@ -1099,7 +1109,9 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> { self.cur_block = Some(el); self.locals.start_block(el); } 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[..]); } - _ => bail!("Unsupported operator: {:?}", op), + _ => bail!(FrontendError::UnsupportedFeature(format!( + "Unsupported operator: {:?}", + op + ))), } Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 66e486e..7fd4848 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,8 @@ mod op_traits; mod ops; pub mod passes; mod scoped_map; +mod errors; pub use ir::*; pub use ops::{Ieee32, Ieee64, Operator}; +pub use errors::*;