Skip to content

Commit 78fbfd1

Browse files
authored
wasm-smith: fix generation of memories with custom page sizes (#1616)
* wasm-smith: fix generation of memories with custom page sizes * Also enable the proposal in our local fuzzing configs
1 parent d643603 commit 78fbfd1

6 files changed

Lines changed: 51 additions & 18 deletions

File tree

crates/wasm-smith/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ wat = { workspace = true, optional = true }
3535
[dev-dependencies]
3636
criterion = { workspace = true }
3737
rand = { workspace = true }
38-
wasmparser = { workspace = true }
38+
wasmparser = { workspace = true, features = ["validate"] }
3939
wasmprinter = { path = "../wasmprinter" }
4040
wat = { path = "../wat" }
4141

crates/wasm-smith/src/config.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -379,17 +379,21 @@ define_config! {
379379
/// wasm proposal.
380380
pub max_memories: usize = 1,
381381

382-
/// The maximum, in 64k Wasm pages, of any 32-bit memory's initial or
383-
/// maximum size.
382+
/// The maximum, in bytes, of any 32-bit memory's initial or maximum
383+
/// size.
384384
///
385-
/// Defaults to 2^16.
386-
pub max_memory32_pages: u64 = 1 << 16,
385+
/// May not be larger than `2**32`.
386+
///
387+
/// Defaults to `2**32`.
388+
pub max_memory32_bytes: u64 = u32::MAX as u64 + 1,
387389

388-
/// The maximum, in 64k Wasm pages, of any 64-bit memory's initial or
389-
/// maximum size.
390+
/// The maximum, in bytes, of any 64-bit memory's initial or maximum
391+
/// size.
392+
///
393+
/// May not be larger than `2**64`.
390394
///
391-
/// Defaults to 2^48.
392-
pub max_memory64_pages: u64 = 1 << 48,
395+
/// Defaults to `2**64`.
396+
pub max_memory64_bytes: u128 = u64::MAX as u128 + 1,
393397

394398
/// The maximum number of modules to use. Defaults to 10.
395399
///
@@ -664,8 +668,8 @@ impl<'a> Arbitrary<'a> for Config {
664668
max_instructions: u.int_in_range(0..=MAX_MAXIMUM)?,
665669
max_memories: u.int_in_range(0..=100)?,
666670
max_tables,
667-
max_memory32_pages: u.int_in_range(0..=1 << 16)?,
668-
max_memory64_pages: u.int_in_range(0..=1 << 48)?,
671+
max_memory32_bytes: u.int_in_range(0..=u32::MAX as u64 + 1)?,
672+
max_memory64_bytes: u.int_in_range(0..=u64::MAX as u128 + 1)?,
669673
min_uleb_size: u.int_in_range(0..=5)?,
670674
bulk_memory_enabled: u.arbitrary()?,
671675
reference_types_enabled,

crates/wasm-smith/src/core.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2558,17 +2558,22 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
25582558
// We want to favor memories <= 1gb in size, allocate at most 16k pages,
25592559
// depending on the maximum number of memories.
25602560
let memory64 = config.memory64_enabled && u.arbitrary()?;
2561-
let page_size = if config.custom_page_sizes_enabled && u.arbitrary()? {
2562-
Some(1 << u.int_in_range(0..=16)?)
2561+
let page_size_log2 = if config.custom_page_sizes_enabled && u.arbitrary()? {
2562+
Some(if u.arbitrary()? { 0 } else { 16 })
25632563
} else {
25642564
None
25652565
};
25662566
let max_inbounds = 16 * 1024 / u64::try_from(config.max_memories).unwrap();
25672567
let min_pages = if config.disallow_traps { Some(1) } else { None };
25682568
let max_pages = min_pages.unwrap_or(0).max(if memory64 {
2569-
config.max_memory64_pages
2569+
u64::try_from(config.max_memory64_bytes >> page_size_log2.unwrap_or(16))
2570+
// Can only fail when we have a custom page size of 1 byte and a
2571+
// memory size of `2**64 == u64::MAX + 1`. In this case, just
2572+
// saturate to `u64::MAX`.
2573+
.unwrap_or(u64::MAX as u64)
25702574
} else {
2571-
config.max_memory32_pages
2575+
// Unlike above, this can never fail.
2576+
u64::try_from(config.max_memory32_bytes >> page_size_log2.unwrap_or(16)).unwrap()
25722577
});
25732578
let (minimum, maximum) = arbitrary_limits64(
25742579
u,
@@ -2582,7 +2587,7 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
25822587
maximum,
25832588
memory64,
25842589
shared,
2585-
page_size_log2: page_size,
2590+
page_size_log2,
25862591
})
25872592
}
25882593

crates/wasm-smith/tests/core.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,25 @@ fn smoke_test_wasm_gc() {
142142
}
143143
}
144144

145+
#[test]
146+
fn smoke_test_wasm_custom_page_sizes() {
147+
let mut rng = SmallRng::seed_from_u64(0);
148+
let mut buf = vec![0; 2048];
149+
for _ in 0..1024 {
150+
rng.fill_bytes(&mut buf);
151+
let mut u = Unstructured::new(&buf);
152+
let config = Config {
153+
custom_page_sizes_enabled: true,
154+
..Config::default()
155+
};
156+
if let Ok(module) = Module::new(config, &mut u) {
157+
let wasm_bytes = module.to_bytes();
158+
let mut validator = Validator::new_with_features(wasm_features());
159+
validate(&mut validator, &wasm_bytes);
160+
}
161+
}
162+
}
163+
145164
fn wasm_features() -> WasmFeatures {
146165
WasmFeatures::all()
147166
}

fuzz/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub fn generate_valid_module(
2828
config.exceptions_enabled = u.arbitrary()?;
2929
config.canonicalize_nans = u.arbitrary()?;
3030
config.tail_call_enabled = u.arbitrary()?;
31+
config.custom_page_sizes_enabled = u.arbitrary()?;
3132

3233
config.gc_enabled = u.arbitrary()?;
3334
config.reference_types_enabled = config.reference_types_enabled || config.gc_enabled;
@@ -91,6 +92,10 @@ pub fn validator_for_config(config: &Config) -> wasmparser::Validator {
9192
features.set(WasmFeatures::MEMORY64, config.memory64_enabled);
9293
features.set(WasmFeatures::THREADS, config.threads_enabled);
9394
features.set(WasmFeatures::EXCEPTIONS, config.exceptions_enabled);
95+
features.set(
96+
WasmFeatures::CUSTOM_PAGE_SIZES,
97+
config.custom_page_sizes_enabled,
98+
);
9499
// TODO: determine our larger story for function-references in
95100
// wasm-tools and whether we should just have a Wasm GC flag since
96101
// function-references is effectively part of the Wasm GC proposal at

fuzz/src/no_traps.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
1616
config.threads_enabled = false;
1717
config.exceptions_enabled = false;
1818
config.gc_enabled = false;
19-
config.max_memory32_pages = config.max_memory32_pages.min(100);
20-
config.max_memory64_pages = config.max_memory64_pages.min(100);
19+
config.max_memory32_bytes = config.max_memory32_bytes.min(1 << 18);
20+
config.max_memory64_bytes = config.max_memory64_bytes.min(1 << 18);
2121

2222
// NB: should re-enable once wasmtime implements the table64 extension
2323
// to the memory64 proposal.

0 commit comments

Comments
 (0)