@@ -487,15 +487,24 @@ execution_handler! {
487487 memory_copy_within( state, & mut args, ip, dst_memory, dst_index, src_index, len) ?;
488488 dispatch!( state, args)
489489 }
490- let dst_memory = utils:: fetch_memory( instance, dst_memory) ;
491- let src_memory = utils:: fetch_memory( instance, src_memory) ;
492- let ( src_memory, dst_memory, fuel) = state
493- . store
494- . inner_mut( )
495- . resolve_memory_pair_and_fuel( & src_memory, & dst_memory) ;
496- // These accesses just perform the bounds checks required by the Wasm spec.
497- let src_bytes = utils:: memory_slice( src_memory, src_index, len) . into_control( ) ?;
498- let dst_bytes = utils:: memory_slice_mut( dst_memory, dst_index, len) . into_control( ) ?;
490+ let src_ptr = unsafe { utils:: load_memory_ptr( instance, src_memory) } ;
491+ let mut dst_ptr = unsafe { utils:: load_memory_ptr( instance, dst_memory) } ;
492+ if src_ptr == dst_ptr {
493+ // Distinct memory indices can still resolve to the same store entity (e.g. the same
494+ // memory imported under two names), so branch on the resolved entity before forming
495+ // the aliasing references below.
496+ memory_copy_within( state, & mut args, ip, dst_memory, dst_index, src_index, len) ?;
497+ dispatch!( state, args)
498+ }
499+ // SAFETY: `src_ptr != dst_ptr`, so these are distinct entities whose references do not
500+ // alias. These accesses just perform the bounds checks required by the Wasm spec.
501+ let src_memory = unsafe { src_ptr. as_ref( ) } ;
502+ let dst_memory = unsafe { dst_ptr. as_mut( ) } ;
503+ let fuel = state. store. inner_mut( ) . fuel_mut( ) ;
504+ let src_bytes = utils:: memory_slice( src_memory, src_index, len)
505+ . into_control( ) ?;
506+ let dst_bytes = utils:: memory_slice_mut( dst_memory, dst_index, len)
507+ . into_control( ) ?;
499508 consume_fuel!(
500509 state,
501510 ip,
@@ -517,8 +526,9 @@ fn memory_copy_within(
517526 src_index : usize ,
518527 len : usize ,
519528) -> Control < ( ) , Break > {
520- let memory = utils:: fetch_memory ( args. instance , dst_memory) ;
521- let ( memory, fuel) = state. store . inner_mut ( ) . resolve_memory_and_fuel_mut ( & memory) ;
529+ // SAFETY: `args.instance` is live and warmed up; `memory` is the only entity accessed here.
530+ let memory = unsafe { utils:: load_memory_ptr ( args. instance , dst_memory) . as_mut ( ) } ;
531+ let fuel = state. store . inner_mut ( ) . fuel_mut ( ) ;
522532 // These accesses just perform the bounds checks required by the Wasm spec.
523533 utils:: memory_slice ( memory, src_index, len) . into_control ( ) ?;
524534 utils:: memory_slice ( memory, dst_index, len) . into_control ( ) ?;
@@ -558,8 +568,9 @@ execution_handler! {
558568 let Ok ( len) = usize :: try_from( len) else {
559569 trap!( TrapCode :: MemoryOutOfBounds )
560570 } ;
561- let memory = utils:: fetch_memory( instance, memory) ;
562- let ( memory, fuel) = state. store. inner_mut( ) . resolve_memory_and_fuel_mut( & memory) ;
571+ // SAFETY: `instance` is live and warmed up; `memory` is the only entity accessed here.
572+ let memory = unsafe { utils:: load_memory_ptr( instance, memory) . as_mut( ) } ;
573+ let fuel = state. store. inner_mut( ) . fuel_mut( ) ;
563574 let slice = utils:: memory_slice_mut( memory, dst, len) . into_control( ) ?;
564575 consume_fuel!( state, ip, args, fuel, |costs| costs. fuel_for_copying_values:: <u8 >( len as u64 ) ) ;
565576 slice. fill( value) ;
@@ -599,13 +610,11 @@ execution_handler! {
599610 let Ok ( len) = usize :: try_from( len) else {
600611 trap!( TrapCode :: MemoryOutOfBounds )
601612 } ;
602- let ( memory, data, fuel) = state
603- . store
604- . inner_mut( )
605- . resolve_memory_init_params(
606- & utils:: fetch_memory( instance, memory) ,
607- & utils:: fetch_data( instance, data) ,
608- ) ;
613+ // SAFETY: `instance` is live and warmed up. `memory` and `data` live in different
614+ // arenas, so their references are to distinct entities and cannot alias.
615+ let memory = unsafe { utils:: load_memory_ptr( instance, memory) . as_mut( ) } ;
616+ let data = unsafe { utils:: load_data_ptr( instance, data) . as_ref( ) } ;
617+ let fuel = state. store. inner_mut( ) . fuel_mut( ) ;
609618 let memory = utils:: memory_slice_mut( memory, dst_index, len) . into_control( ) ?;
610619 let Some ( data) = data
611620 . bytes( )
@@ -731,32 +740,26 @@ execution_handler! {
731740 let dst: u64 = args. get( dst) ;
732741 let src: u64 = args. get( src) ;
733742 let len: u64 = args. get( len) ;
734- if dst_table == src_table {
735- // Case: copy within the same table
736- let table = utils:: fetch_table( instance, dst_table) ;
737- let ( table, fuel) = state. store. inner_mut( ) . resolve_table_and_fuel_mut( & table) ;
738- if let Err ( error) = table. copy_within( dst, src, len, Some ( fuel) ) {
739- let trap_code = match error {
740- TableError :: CopyOutOfBounds => TrapCode :: TableOutOfBounds ,
741- TableError :: OutOfSystemMemory => TrapCode :: OutOfSystemMemory ,
742- TableError :: OutOfFuel { required_fuel } => {
743- args. set_ip( ip) ;
744- out_of_fuel!( state, args, required_fuel)
745- }
746- _ => panic!( "table.copy: unexpected error: {error}" ) ,
747- } ;
748- trap!( trap_code)
749- }
750- dispatch!( state, args)
751- }
752- // Case: copy between two different tables
753- let dst_table = utils:: fetch_table( instance, dst_table) ;
754- let src_table = utils:: fetch_table( instance, src_table) ;
755- let ( dst_table, src_table, fuel) = state
756- . store
757- . inner_mut( )
758- . resolve_table_pair_and_fuel( & dst_table, & src_table) ;
759- if let Err ( error) = CoreTable :: copy( dst_table, dst, src_table, src, len, Some ( fuel) ) {
743+ let src_ptr = unsafe { utils:: load_table_ptr( instance, src_table) } ;
744+ let mut dst_ptr = unsafe { utils:: load_table_ptr( instance, dst_table) } ;
745+ // Distinct table indices can still resolve to the same store entity (e.g. the same table
746+ // imported under two names), so branch on the resolved entity, not just the index.
747+ let result = if src_ptr == dst_ptr {
748+ // Case: copy within the same table.
749+ // SAFETY: `dst_ptr` is warmed up and is the only entity accessed here.
750+ let table = unsafe { dst_ptr. as_mut( ) } ;
751+ let fuel = state. store. inner_mut( ) . fuel_mut( ) ;
752+ table. copy_within( dst, src, len, Some ( fuel) )
753+ } else {
754+ // Case: copy between two distinct tables.
755+ // SAFETY: `src_ptr != dst_ptr`, so these are distinct entities whose references do
756+ // not alias.
757+ let src_table = unsafe { src_ptr. as_ref( ) } ;
758+ let dst_table = unsafe { dst_ptr. as_mut( ) } ;
759+ let fuel = state. store. inner_mut( ) . fuel_mut( ) ;
760+ CoreTable :: copy( dst_table, dst, src_table, src, len, Some ( fuel) )
761+ } ;
762+ if let Err ( error) = result {
760763 let trap_code = match error {
761764 TableError :: CopyOutOfBounds => TrapCode :: TableOutOfBounds ,
762765 TableError :: OutOfSystemMemory => TrapCode :: OutOfSystemMemory ,
@@ -794,8 +797,9 @@ execution_handler! {
794797 let dst: u64 = args. get( dst) ;
795798 let len: u64 = args. get( len) ;
796799 let value: RawRef = args. get( value) ;
797- let table = utils:: fetch_table( instance, table) ;
798- let ( table, fuel) = state. store. inner_mut( ) . resolve_table_and_fuel_mut( & table) ;
800+ // SAFETY: `instance` is live and warmed up; `table` is the only entity accessed here.
801+ let table = unsafe { utils:: load_table_ptr( instance, table) . as_mut( ) } ;
802+ let fuel = state. store. inner_mut( ) . fuel_mut( ) ;
799803 if let Err ( error) = table. fill_raw( dst, value, len, Some ( fuel) ) {
800804 let trap_code = match error {
801805 TableError :: OutOfSystemMemory => TrapCode :: OutOfSystemMemory ,
@@ -835,12 +839,11 @@ execution_handler! {
835839 let dst: u64 = args. get( dst) ;
836840 let src: u32 = args. get( src) ;
837841 let len: u32 = args. get( len) ;
838- let table = utils:: fetch_table( args. instance, table) ;
839- let elem = utils:: fetch_elem( args. instance, elem) ;
840- let ( table, element, fuel) = state
841- . store
842- . inner_mut( )
843- . resolve_table_init_params( & table, & elem) ;
842+ // SAFETY: `args.instance` is live and warmed up. `table` and `elem` live in different
843+ // arenas, so their references are to distinct entities and cannot alias.
844+ let table = unsafe { utils:: load_table_ptr( args. instance, table) . as_mut( ) } ;
845+ let element = unsafe { utils:: load_elem_ptr( args. instance, elem) . as_ref( ) } ;
846+ let fuel = state. store. inner_mut( ) . fuel_mut( ) ;
844847 if let Err ( error) = table. init( element. as_ref( ) , dst, src, len, Some ( fuel) ) {
845848 let trap_code = match error {
846849 TableError :: OutOfSystemMemory => TrapCode :: OutOfSystemMemory ,
0 commit comments