Skip to content

Commit b04b598

Browse files
authored
wasm-smith: Minor fixes for generating memories with custom page sizes (#1617)
1 parent 78fbfd1 commit b04b598

1 file changed

Lines changed: 51 additions & 18 deletions

File tree

crates/wasm-smith/src/core.rs

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,12 +2472,27 @@ pub(crate) fn arbitrary_limits64(
24722472
max_required: bool,
24732473
max_inbounds: u64,
24742474
) -> Result<(u64, Option<u64>)> {
2475+
assert!(
2476+
min_minimum.unwrap_or(0) <= max_minimum,
2477+
"{} <= {max_minimum}",
2478+
min_minimum.unwrap_or(0),
2479+
);
2480+
assert!(
2481+
min_minimum.unwrap_or(0) <= max_inbounds,
2482+
"{} <= {max_inbounds}",
2483+
min_minimum.unwrap_or(0),
2484+
);
2485+
24752486
let min = gradually_grow(u, min_minimum.unwrap_or(0), max_inbounds, max_minimum)?;
2487+
assert!(min <= max_minimum, "{min} <= {max_minimum}");
2488+
24762489
let max = if max_required || u.arbitrary().unwrap_or(false) {
24772490
Some(u.int_in_range(min..=max_minimum)?)
24782491
} else {
24792492
None
24802493
};
2494+
assert!(min <= max.unwrap_or(min), "{min} <= {}", max.unwrap_or(min));
2495+
24812496
Ok((min, max))
24822497
}
24832498

@@ -2555,15 +2570,14 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
25552570
// When threads are enabled, we only want to generate shared memories about
25562571
// 25% of the time.
25572572
let shared = config.threads_enabled && u.ratio(1, 4)?;
2558-
// We want to favor memories <= 1gb in size, allocate at most 16k pages,
2559-
// depending on the maximum number of memories.
2573+
25602574
let memory64 = config.memory64_enabled && u.arbitrary()?;
25612575
let page_size_log2 = if config.custom_page_sizes_enabled && u.arbitrary()? {
25622576
Some(if u.arbitrary()? { 0 } else { 16 })
25632577
} else {
25642578
None
25652579
};
2566-
let max_inbounds = 16 * 1024 / u64::try_from(config.max_memories).unwrap();
2580+
25672581
let min_pages = if config.disallow_traps { Some(1) } else { None };
25682582
let max_pages = min_pages.unwrap_or(0).max(if memory64 {
25692583
u64::try_from(config.max_memory64_bytes >> page_size_log2.unwrap_or(16))
@@ -2572,16 +2586,27 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
25722586
// saturate to `u64::MAX`.
25732587
.unwrap_or(u64::MAX as u64)
25742588
} else {
2575-
// Unlike above, this can never fail.
2576-
u64::try_from(config.max_memory32_bytes >> page_size_log2.unwrap_or(16)).unwrap()
2589+
u32::try_from(config.max_memory32_bytes >> page_size_log2.unwrap_or(16))
2590+
// Similar case as above, but while we could represent `2**32` in our
2591+
// `u64` here, 32-bit memories' limits must fit in a `u32`.
2592+
.unwrap_or(u32::MAX)
2593+
.into()
25772594
});
2595+
2596+
// We want to favor keeping the total memories <= 1gb in size.
2597+
let max_all_mems_in_bytes = 1 << 30;
2598+
let max_this_mem_in_bytes = max_all_mems_in_bytes / u64::try_from(config.max_memories).unwrap();
2599+
let max_inbounds = max_this_mem_in_bytes >> page_size_log2.unwrap_or(16);
2600+
let max_inbounds = max_inbounds.clamp(min_pages.unwrap_or(0), max_pages);
2601+
25782602
let (minimum, maximum) = arbitrary_limits64(
25792603
u,
25802604
min_pages,
25812605
max_pages,
25822606
config.memory_max_size_required || shared,
2583-
max_inbounds.min(max_pages),
2607+
max_inbounds,
25842608
)?;
2609+
25852610
Ok(MemoryType {
25862611
minimum,
25872612
maximum,
@@ -2615,18 +2640,26 @@ fn gradually_grow(u: &mut Unstructured, min: u64, max_inbounds: u64, max: u64) -
26152640
if min == max {
26162641
return Ok(min);
26172642
}
2618-
let min = min as f64;
2619-
let max = max as f64;
2620-
let max_inbounds = max_inbounds as f64;
2621-
let x = u.arbitrary::<u32>()?;
2622-
let x = f64::from(x);
2623-
let x = map_custom(
2624-
x,
2625-
f64::from(u32::MIN)..f64::from(u32::MAX),
2626-
min..max_inbounds,
2627-
min..max,
2628-
);
2629-
return Ok(x.round() as u64);
2643+
let x = {
2644+
let min = min as f64;
2645+
let max = max as f64;
2646+
let max_inbounds = max_inbounds as f64;
2647+
let x = u.arbitrary::<u32>()?;
2648+
let x = f64::from(x);
2649+
let x = map_custom(
2650+
x,
2651+
f64::from(u32::MIN)..f64::from(u32::MAX),
2652+
min..max_inbounds,
2653+
min..max,
2654+
);
2655+
assert!(min <= x, "{min} <= {x}");
2656+
assert!(x <= max, "{x} <= {max}");
2657+
x.round() as u64
2658+
};
2659+
2660+
// Conversion between `u64` and `f64` is lossy, especially for large
2661+
// numbers, so just clamp the final result.
2662+
return Ok(x.clamp(min, max));
26302663

26312664
/// Map a value from within the input range to the output range(s).
26322665
///

0 commit comments

Comments
 (0)