Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🏗️ Move wasm-smith's non-trapping mode logic to CodeBuilder #769

Merged
merged 28 commits into from Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1fd44cf
Change CodeBuilder functions to emit multiple instructions
itsrainy Sep 14, 2022
a9fc52e
Move no-trapping logic to a code_builder module
itsrainy Sep 20, 2022
0123e51
Add configuration option to disallow traps
itsrainy Sep 20, 2022
77bc09f
Don't generate trapping instructions that haven't been handled yet
itsrainy Sep 20, 2022
e21bd93
Remove unused import_count function
itsrainy Sep 20, 2022
2fcf98e
Update crates/wasm-smith/src/core/code_builder.rs
itsrainy Sep 20, 2022
9ec356a
Add first pass at fuzzer to verify non-trapping mode does not trap
itsrainy Sep 22, 2022
2b24907
rebase
itsrainy Oct 3, 2022
df12a02
Address review comments
itsrainy Oct 4, 2022
1bd49f4
Handle table and element segments in no-trapping mode
itsrainy Oct 24, 2022
c21d147
Fix smoke test for non-trapping mode
itsrainy Oct 25, 2022
bb29731
Clamp generated data offset to min memory size minus data length
itsrainy Oct 25, 2022
1f82680
Handle running out of fuel during instantiation
itsrainy Oct 25, 2022
da9a663
Don't generate simd instructions in non-trapping mode
itsrainy Oct 26, 2022
b2a21dd
Use ne rather than eq to check for NaN values. NaN can't be checked
itsrainy Oct 26, 2022
e90582e
Perform bounds checking for trunc instructions in non-trapping mode
itsrainy Oct 26, 2022
62c27b3
Adjust fuel to avoid "out of fuel" error on consume(0)
itsrainy Oct 26, 2022
4fda694
Explicitly specify the largest/smallest i64 that can be represented as
itsrainy Oct 26, 2022
d091301
As part of our non-trapping logic for load operations, we emit instru…
itsrainy Oct 27, 2022
a42cabf
Don't emit unreachable instructions in non-trapping mode
itsrainy Oct 27, 2022
1b35fdb
Explicitly specify max/min values for f32
itsrainy Nov 2, 2022
9c9f68b
Handle min/max f32 values representable as i32
itsrainy Nov 3, 2022
9dde658
Ensure stores/loads with negative addresses don't trap
itsrainy Nov 3, 2022
eed452c
Don't allow stores with memarg.offset==i64::MAX while in non-trapping…
itsrainy Nov 3, 2022
d2df2f8
Refactor mem offset calculation to be in one place
itsrainy Nov 4, 2022
7ef8bac
Use a ResourceLimiter to prevent libfuzzer from running out of memory.
itsrainy Nov 4, 2022
3a761e6
Clean up code a little bit
itsrainy Nov 7, 2022
9a1a86f
Add doc to `disallow_traps` explaining StackOverflow traps
itsrainy Nov 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 1 addition & 32 deletions crates/fuzz-stats/src/bin/failed-instantiations.rs
Expand Up @@ -118,7 +118,7 @@ impl State {
let module = Module::new(&self.engine, &wasm).expect("failed to compile module");
let mut store = Store::new(
&self.engine,
StoreLimits {
fuzz_stats::limits::StoreLimits {
remaining_memory: 1 << 30,
oom: false,
},
Expand Down Expand Up @@ -181,34 +181,3 @@ impl State {
println!();
}
}

struct StoreLimits {
remaining_memory: usize,
oom: bool,
}

impl StoreLimits {
fn alloc(&mut self, amt: usize) -> bool {
match self.remaining_memory.checked_sub(amt) {
Some(mem) => {
self.remaining_memory = mem;
true
}
None => {
self.oom = true;
false
}
}
}
}

impl ResourceLimiter for StoreLimits {
fn memory_growing(&mut self, current: usize, desired: usize, _maximum: Option<usize>) -> bool {
self.alloc(desired - current)
}

fn table_growing(&mut self, current: u32, desired: u32, _maximum: Option<u32>) -> bool {
let delta = (desired - current) as usize * std::mem::size_of::<usize>();
self.alloc(delta)
}
}
1 change: 1 addition & 0 deletions crates/fuzz-stats/src/lib.rs
@@ -1 +1,2 @@
pub mod dummy;
pub mod limits;
31 changes: 31 additions & 0 deletions crates/fuzz-stats/src/limits.rs
@@ -0,0 +1,31 @@
use wasmtime::*;
pub struct StoreLimits {
pub remaining_memory: usize,
pub oom: bool,
}

impl StoreLimits {
fn alloc(&mut self, amt: usize) -> bool {
match self.remaining_memory.checked_sub(amt) {
Some(mem) => {
self.remaining_memory = mem;
true
}
None => {
self.oom = true;
false
}
}
}
}

impl ResourceLimiter for StoreLimits {
fn memory_growing(&mut self, current: usize, desired: usize, _maximum: Option<usize>) -> bool {
self.alloc(desired - current)
}

fn table_growing(&mut self, current: u32, desired: u32, _maximum: Option<u32>) -> bool {
let delta = (desired - current) as usize * std::mem::size_of::<usize>();
self.alloc(delta)
}
}
25 changes: 25 additions & 0 deletions crates/wasm-smith/src/config.rs
Expand Up @@ -449,6 +449,25 @@ pub trait Config: 'static + std::fmt::Debug {
fn threads_enabled(&self) -> bool {
false
}

/// Returns whether we should avoid generating code that will possibly trap.
///
/// For some trapping instructions, this will emit extra instructions to
/// ensure they don't trap, while some instructions will simply be excluded.
/// In cases where we would run into a trap, we instead choose some
/// arbitrary non-trapping behavior. For example, if we detect that a Load
/// instruction would attempt to access out-of-bounds memory, we instead
/// pretend the load succeeded and push 0 onto the stack.
///
/// One type of trap that we can't currently avoid is StackOverflow. Even
/// when `disallow_traps` is set to true, wasm-smith will eventually
/// generate a program that infinitely recurses, causing the call stack to
/// be exhausted.
///
/// Defaults to `false`.
fn disallow_traps(&self) -> bool {
false
}
}

/// The default configuration.
Expand Down Expand Up @@ -476,6 +495,7 @@ pub struct SwarmConfig {
pub available_imports: Option<Vec<u8>>,
pub bulk_memory_enabled: bool,
pub canonicalize_nans: bool,
pub disallow_traps: bool,
pub exceptions_enabled: bool,
pub export_everything: bool,
pub max_aliases: usize,
Expand Down Expand Up @@ -597,6 +617,7 @@ impl<'a> Arbitrary<'a> for SwarmConfig {
available_imports: None,
threads_enabled: false,
export_everything: false,
disallow_traps: false,
})
}
}
Expand Down Expand Up @@ -795,4 +816,8 @@ impl Config for SwarmConfig {
fn table_max_size_required(&self) -> bool {
self.table_max_size_required
}

fn disallow_traps(&self) -> bool {
self.disallow_traps
}
}