Skip to content

Commit

Permalink
Update memory configuration during fuzzing (#9567)
Browse files Browse the repository at this point in the history
This commit updates how the `NormalMemoryConfig` works during fuzzing.
Previously this was either 0 or an arbitrary 32-bit number. This ended
up not not handling cases such as 4GiB exactly which is 1 larger than
the 32-bit range. Additionally 33+-bit numbers were never tested. This
intends to expand our fuzz coverage here by most of the time using the
default settings of `Config` and then otherwise selecting amongst an
"interesting" set of numbers such as 0, powers of two, etc.
  • Loading branch information
alexcrichton authored Nov 5, 2024
1 parent 8818b25 commit cc6cf63
Showing 1 changed file with 48 additions and 9 deletions.
57 changes: 48 additions & 9 deletions crates/fuzzing/src/generators/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,27 +145,66 @@ pub struct NormalMemoryConfig {

impl<'a> Arbitrary<'a> for NormalMemoryConfig {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
// This attempts to limit memory and guard sizes to 32-bit ranges so
// we don't exhaust a 64-bit address space easily.
Ok(Self {
memory_reservation: <Option<u32> as Arbitrary>::arbitrary(u)?.map(Into::into),
memory_guard_size: <Option<u32> as Arbitrary>::arbitrary(u)?.map(Into::into),
memory_reservation_for_growth: <Option<u32> as Arbitrary>::arbitrary(u)?
.map(Into::into),
// Allow up to 8GiB reservations of the virtual address space for
// the initial memory reservation.
memory_reservation: interesting_virtual_memory_size(u, 33)?,

// Allow up to 4GiB guard page reservations to be made.
memory_guard_size: interesting_virtual_memory_size(u, 32)?,

// Allow up up to 1GiB extra memory to grow into for dynamic
// memories.
memory_reservation_for_growth: interesting_virtual_memory_size(u, 30)?,

guard_before_linear_memory: u.arbitrary()?,
cranelift_enable_heap_access_spectre_mitigations: u.arbitrary()?,
memory_init_cow: u.arbitrary()?,
})
}
}

/// Helper function to generate "interesting numbers" for virtual memory
/// configuration options that `Config` supports.
fn interesting_virtual_memory_size(
u: &mut Unstructured<'_>,
max_log2: u32,
) -> arbitrary::Result<Option<u64>> {
// Most of the time return "none" meaning "use the default settings".
if u.ratio(3, 4)? {
return Ok(None);
}

// Otherwise do a split between various strategies.
#[derive(Arbitrary)]
enum Interesting {
Zero,
PowerOfTwo,
Arbitrary,
}

let size = match u.arbitrary()? {
Interesting::Zero => 0,
Interesting::PowerOfTwo => 1 << u.int_in_range(0..=max_log2)?,
Interesting::Arbitrary => u.int_in_range(0..=1 << max_log2)?,
};
Ok(Some(size))
}

impl NormalMemoryConfig {
/// Apply this memory configuration to the given `wasmtime::Config`.
pub fn apply_to(&self, config: &mut wasmtime::Config) {
if let Some(n) = self.memory_reservation {
config.memory_reservation(n);
}
if let Some(n) = self.memory_guard_size {
config.memory_guard_size(n);
}
if let Some(n) = self.memory_reservation_for_growth {
config.memory_reservation_for_growth(n);
}

config
.memory_reservation(self.memory_reservation.unwrap_or(0))
.memory_guard_size(self.memory_guard_size.unwrap_or(0))
.memory_reservation_for_growth(self.memory_reservation_for_growth.unwrap_or(0))
.guard_before_linear_memory(self.guard_before_linear_memory)
.memory_init_cow(self.memory_init_cow);

Expand Down

0 comments on commit cc6cf63

Please sign in to comment.