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

Update memory configuration during fuzzing #9567

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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