@@ -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