Browse Source

Feature - Stricter ABI and runtime constraints (#7113)

* Renames bpf_account_data_direct_mapping => stricter_abi_and_runtime_constraints.

* Adds InvokeContext::account_data_direct_mapping.

* Separates stricter_abi_and_runtime_constraints from account_data_direct_mapping.

* Rekeys stricter_abi_and_runtime_constraints.

* Adjusts test_serialize_parameters_with_many_accounts().
Alexander Meißner 3 months ago
parent
commit
898ded76b7

+ 5 - 4
feature-set/src/lib.rs

@@ -106,7 +106,8 @@ impl FeatureSet {
                 .is_active(&move_precompile_verification_to_svm::id()),
                 .is_active(&move_precompile_verification_to_svm::id()),
             remove_accounts_executable_flag_checks: self
             remove_accounts_executable_flag_checks: self
                 .is_active(&remove_accounts_executable_flag_checks::id()),
                 .is_active(&remove_accounts_executable_flag_checks::id()),
-            bpf_account_data_direct_mapping: self.is_active(&bpf_account_data_direct_mapping::id()),
+            stricter_abi_and_runtime_constraints: self
+                .is_active(&stricter_abi_and_runtime_constraints::id()),
             enable_bpf_loader_set_authority_checked_ix: self
             enable_bpf_loader_set_authority_checked_ix: self
                 .is_active(&enable_bpf_loader_set_authority_checked_ix::id()),
                 .is_active(&enable_bpf_loader_set_authority_checked_ix::id()),
             enable_loader_v4: self.is_active(&enable_loader_v4::id()),
             enable_loader_v4: self.is_active(&enable_loader_v4::id()),
@@ -752,8 +753,8 @@ pub mod apply_cost_tracker_during_replay {
     solana_pubkey::declare_id!("2ry7ygxiYURULZCrypHhveanvP5tzZ4toRwVp89oCNSj");
     solana_pubkey::declare_id!("2ry7ygxiYURULZCrypHhveanvP5tzZ4toRwVp89oCNSj");
 }
 }
 
 
-pub mod bpf_account_data_direct_mapping {
-    solana_pubkey::declare_id!("1ncomp1ete111111111111111111111111111111111");
+pub mod stricter_abi_and_runtime_constraints {
+    solana_pubkey::declare_id!("C37iaPi6VE4CZDueU1vL8y6pGp5i8amAbEsF31xzz723");
 }
 }
 
 
 pub mod add_set_tx_loaded_accounts_data_size_instruction {
 pub mod add_set_tx_loaded_accounts_data_size_instruction {
@@ -1279,7 +1280,7 @@ pub static FEATURE_NAMES: LazyLock<AHashMap<Pubkey, &'static str>> = LazyLock::n
         (clean_up_delegation_errors::id(), "Return InsufficientDelegation instead of InsufficientFunds or InsufficientStake where applicable #31206"),
         (clean_up_delegation_errors::id(), "Return InsufficientDelegation instead of InsufficientFunds or InsufficientStake where applicable #31206"),
         (vote_state_add_vote_latency::id(), "replace Lockout with LandedVote (including vote latency) in vote state #31264"),
         (vote_state_add_vote_latency::id(), "replace Lockout with LandedVote (including vote latency) in vote state #31264"),
         (checked_arithmetic_in_fee_validation::id(), "checked arithmetic in fee validation #31273"),
         (checked_arithmetic_in_fee_validation::id(), "checked arithmetic in fee validation #31273"),
-        (bpf_account_data_direct_mapping::id(), "use memory regions to map account data into the rbpf vm instead of copying the data"),
+        (stricter_abi_and_runtime_constraints::id(), "use memory regions to map account data into the rbpf vm instead of copying the data"),
         (last_restart_slot_sysvar::id(), "enable new sysvar last_restart_slot"),
         (last_restart_slot_sysvar::id(), "enable new sysvar last_restart_slot"),
         (reduce_stake_warmup_cooldown::id(), "reduce stake warmup cooldown from 25% to 9%"),
         (reduce_stake_warmup_cooldown::id(), "reduce stake warmup cooldown from 25% to 9%"),
         (revise_turbine_epoch_stakes::id(), "revise turbine epoch stakes"),
         (revise_turbine_epoch_stakes::id(), "revise turbine epoch stakes"),

+ 2 - 1
ledger-tool/src/program.rs

@@ -535,7 +535,8 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) {
             .transaction_context
             .transaction_context
             .get_current_instruction_context()
             .get_current_instruction_context()
             .unwrap(),
             .unwrap(),
-        false, // direct_mapping
+        false, // stricter_abi_and_runtime_constraints
+        false, // account_data_direct_mapping
         true,  // for mask_out_rent_epoch_in_vm_serialization
         true,  // for mask_out_rent_epoch_in_vm_serialization
     )
     )
     .unwrap();
     .unwrap();

+ 3 - 0
program-runtime/src/invoke_context.rs

@@ -202,6 +202,8 @@ pub struct InvokeContext<'a> {
     pub timings: ExecuteDetailsTimings,
     pub timings: ExecuteDetailsTimings,
     pub syscall_context: Vec<Option<SyscallContext>>,
     pub syscall_context: Vec<Option<SyscallContext>>,
     traces: Vec<Vec<[u64; 12]>>,
     traces: Vec<Vec<[u64; 12]>>,
+    /// Stops copying account data if stricter_abi_and_runtime_constraints is enabled
+    pub account_data_direct_mapping: bool,
 }
 }
 
 
 impl<'a> InvokeContext<'a> {
 impl<'a> InvokeContext<'a> {
@@ -226,6 +228,7 @@ impl<'a> InvokeContext<'a> {
             timings: ExecuteDetailsTimings::default(),
             timings: ExecuteDetailsTimings::default(),
             syscall_context: Vec::new(),
             syscall_context: Vec::new(),
             traces: Vec::new(),
             traces: Vec::new(),
+            account_data_direct_mapping: false,
         }
         }
     }
     }
 
 

+ 145 - 63
program-runtime/src/serialization.rs

@@ -22,7 +22,22 @@ use {
 /// SBF VM.
 /// SBF VM.
 const MAX_INSTRUCTION_ACCOUNTS: u8 = NON_DUP_MARKER;
 const MAX_INSTRUCTION_ACCOUNTS: u8 = NON_DUP_MARKER;
 
 
-/// Creates the account data direct mapping in serialization and CPI return
+/// Modifies the memory mapping in serialization and CPI return for stricter_abi_and_runtime_constraints
+pub fn modify_memory_region_of_account(
+    account: &mut BorrowedAccount<'_>,
+    region: &mut MemoryRegion,
+) {
+    region.len = account.get_data().len() as u64;
+    if account.can_data_be_changed().is_ok() {
+        region.writable = true;
+        region.access_violation_handler_payload = Some(account.get_index_in_transaction());
+    } else {
+        region.writable = false;
+        region.access_violation_handler_payload = None;
+    }
+}
+
+/// Creates the memory mapping in serialization and CPI return for account_data_direct_mapping
 pub fn create_memory_region_of_account(
 pub fn create_memory_region_of_account(
     account: &mut BorrowedAccount<'_>,
     account: &mut BorrowedAccount<'_>,
     vaddr: u64,
     vaddr: u64,
@@ -51,18 +66,26 @@ struct Serializer {
     vaddr: u64,
     vaddr: u64,
     region_start: usize,
     region_start: usize,
     is_loader_v1: bool,
     is_loader_v1: bool,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
 }
 }
 
 
 impl Serializer {
 impl Serializer {
-    fn new(size: usize, start_addr: u64, is_loader_v1: bool, direct_mapping: bool) -> Serializer {
+    fn new(
+        size: usize,
+        start_addr: u64,
+        is_loader_v1: bool,
+        stricter_abi_and_runtime_constraints: bool,
+        account_data_direct_mapping: bool,
+    ) -> Serializer {
         Serializer {
         Serializer {
             buffer: AlignedMemory::with_capacity(size),
             buffer: AlignedMemory::with_capacity(size),
             regions: Vec::new(),
             regions: Vec::new(),
             region_start: 0,
             region_start: 0,
             vaddr: start_addr,
             vaddr: start_addr,
             is_loader_v1,
             is_loader_v1,
-            direct_mapping,
+            stricter_abi_and_runtime_constraints,
+            account_data_direct_mapping,
         }
         }
     }
     }
 
 
@@ -109,13 +132,26 @@ impl Serializer {
         &mut self,
         &mut self,
         account: &mut BorrowedAccount<'_>,
         account: &mut BorrowedAccount<'_>,
     ) -> Result<u64, InstructionError> {
     ) -> Result<u64, InstructionError> {
-        let vm_data_addr = if !self.direct_mapping {
+        if !self.stricter_abi_and_runtime_constraints {
             let vm_data_addr = self.vaddr.saturating_add(self.buffer.len() as u64);
             let vm_data_addr = self.vaddr.saturating_add(self.buffer.len() as u64);
             self.write_all(account.get_data());
             self.write_all(account.get_data());
-            vm_data_addr
+            if !self.is_loader_v1 {
+                let align_offset =
+                    (account.get_data().len() as *const u8).align_offset(BPF_ALIGN_OF_U128);
+                self.fill_write(MAX_PERMITTED_DATA_INCREASE + align_offset, 0)
+                    .map_err(|_| InstructionError::InvalidArgument)?;
+            }
+            Ok(vm_data_addr)
         } else {
         } else {
             self.push_region();
             self.push_region();
-            let vaddr = self.vaddr;
+            let vm_data_addr = self.vaddr;
+            if !self.account_data_direct_mapping {
+                self.write_all(account.get_data());
+                if !self.is_loader_v1 {
+                    self.fill_write(MAX_PERMITTED_DATA_INCREASE, 0)
+                        .map_err(|_| InstructionError::InvalidArgument)?;
+                }
+            }
             let address_space_reserved_for_account = if !self.is_loader_v1 {
             let address_space_reserved_for_account = if !self.is_loader_v1 {
                 account
                 account
                     .get_data()
                     .get_data()
@@ -125,32 +161,35 @@ impl Serializer {
                 account.get_data().len()
                 account.get_data().len()
             };
             };
             if address_space_reserved_for_account > 0 {
             if address_space_reserved_for_account > 0 {
-                let new_region = create_memory_region_of_account(account, self.vaddr)?;
-                self.vaddr += address_space_reserved_for_account as u64;
-                self.regions.push(new_region);
+                if !self.account_data_direct_mapping {
+                    self.push_region();
+                    let region = self.regions.last_mut().unwrap();
+                    modify_memory_region_of_account(account, region);
+                } else {
+                    let new_region = create_memory_region_of_account(account, self.vaddr)?;
+                    self.vaddr += address_space_reserved_for_account as u64;
+                    self.regions.push(new_region);
+                }
             }
             }
-            vaddr
-        };
-
-        if !self.is_loader_v1 {
-            let align_offset =
-                (account.get_data().len() as *const u8).align_offset(BPF_ALIGN_OF_U128);
-            if !self.direct_mapping {
-                self.fill_write(MAX_PERMITTED_DATA_INCREASE + align_offset, 0)
-                    .map_err(|_| InstructionError::InvalidArgument)?;
-            } else {
-                // The deserialization code is going to align the vm_addr to
-                // BPF_ALIGN_OF_U128. Always add one BPF_ALIGN_OF_U128 worth of
-                // padding and shift the start of the next region, so that once
-                // vm_addr is aligned, the corresponding host_addr is aligned
-                // too.
-                self.fill_write(BPF_ALIGN_OF_U128, 0)
-                    .map_err(|_| InstructionError::InvalidArgument)?;
-                self.region_start += BPF_ALIGN_OF_U128.saturating_sub(align_offset);
+            if !self.is_loader_v1 {
+                let align_offset =
+                    (account.get_data().len() as *const u8).align_offset(BPF_ALIGN_OF_U128);
+                if !self.account_data_direct_mapping {
+                    self.fill_write(align_offset, 0)
+                        .map_err(|_| InstructionError::InvalidArgument)?;
+                } else {
+                    // The deserialization code is going to align the vm_addr to
+                    // BPF_ALIGN_OF_U128. Always add one BPF_ALIGN_OF_U128 worth of
+                    // padding and shift the start of the next region, so that once
+                    // vm_addr is aligned, the corresponding host_addr is aligned
+                    // too.
+                    self.fill_write(BPF_ALIGN_OF_U128, 0)
+                        .map_err(|_| InstructionError::InvalidArgument)?;
+                    self.region_start += BPF_ALIGN_OF_U128.saturating_sub(align_offset);
+                }
             }
             }
+            Ok(vm_data_addr)
         }
         }
-
-        Ok(vm_data_addr)
     }
     }
 
 
     fn push_region(&mut self) {
     fn push_region(&mut self) {
@@ -186,7 +225,8 @@ impl Serializer {
 pub fn serialize_parameters(
 pub fn serialize_parameters(
     transaction_context: &TransactionContext,
     transaction_context: &TransactionContext,
     instruction_context: &InstructionContext,
     instruction_context: &InstructionContext,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
     mask_out_rent_epoch_in_vm_serialization: bool,
     mask_out_rent_epoch_in_vm_serialization: bool,
 ) -> Result<
 ) -> Result<
     (
     (
@@ -235,7 +275,8 @@ pub fn serialize_parameters(
             accounts,
             accounts,
             instruction_context.get_instruction_data(),
             instruction_context.get_instruction_data(),
             &program_id,
             &program_id,
-            direct_mapping,
+            stricter_abi_and_runtime_constraints,
+            account_data_direct_mapping,
             mask_out_rent_epoch_in_vm_serialization,
             mask_out_rent_epoch_in_vm_serialization,
         )
         )
     } else {
     } else {
@@ -243,7 +284,8 @@ pub fn serialize_parameters(
             accounts,
             accounts,
             instruction_context.get_instruction_data(),
             instruction_context.get_instruction_data(),
             &program_id,
             &program_id,
-            direct_mapping,
+            stricter_abi_and_runtime_constraints,
+            account_data_direct_mapping,
             mask_out_rent_epoch_in_vm_serialization,
             mask_out_rent_epoch_in_vm_serialization,
         )
         )
     }
     }
@@ -252,7 +294,8 @@ pub fn serialize_parameters(
 pub fn deserialize_parameters(
 pub fn deserialize_parameters(
     transaction_context: &TransactionContext,
     transaction_context: &TransactionContext,
     instruction_context: &InstructionContext,
     instruction_context: &InstructionContext,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
     buffer: &[u8],
     buffer: &[u8],
     accounts_metadata: &[SerializedAccountMetadata],
     accounts_metadata: &[SerializedAccountMetadata],
 ) -> Result<(), InstructionError> {
 ) -> Result<(), InstructionError> {
@@ -265,7 +308,8 @@ pub fn deserialize_parameters(
         deserialize_parameters_unaligned(
         deserialize_parameters_unaligned(
             transaction_context,
             transaction_context,
             instruction_context,
             instruction_context,
-            direct_mapping,
+            stricter_abi_and_runtime_constraints,
+            account_data_direct_mapping,
             buffer,
             buffer,
             account_lengths,
             account_lengths,
         )
         )
@@ -273,7 +317,8 @@ pub fn deserialize_parameters(
         deserialize_parameters_aligned(
         deserialize_parameters_aligned(
             transaction_context,
             transaction_context,
             instruction_context,
             instruction_context,
-            direct_mapping,
+            stricter_abi_and_runtime_constraints,
+            account_data_direct_mapping,
             buffer,
             buffer,
             account_lengths,
             account_lengths,
         )
         )
@@ -284,7 +329,8 @@ fn serialize_parameters_unaligned(
     accounts: Vec<SerializeAccount>,
     accounts: Vec<SerializeAccount>,
     instruction_data: &[u8],
     instruction_data: &[u8],
     program_id: &Pubkey,
     program_id: &Pubkey,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
     mask_out_rent_epoch_in_vm_serialization: bool,
     mask_out_rent_epoch_in_vm_serialization: bool,
 ) -> Result<
 ) -> Result<
     (
     (
@@ -309,7 +355,7 @@ fn serialize_parameters_unaligned(
                 + size_of::<Pubkey>() // owner
                 + size_of::<Pubkey>() // owner
                 + size_of::<u8>() // executable
                 + size_of::<u8>() // executable
                 + size_of::<u64>(); // rent_epoch
                 + size_of::<u64>(); // rent_epoch
-                if !direct_mapping {
+                if !(stricter_abi_and_runtime_constraints && account_data_direct_mapping) {
                     size += account.get_data().len();
                     size += account.get_data().len();
                 }
                 }
             }
             }
@@ -319,7 +365,13 @@ fn serialize_parameters_unaligned(
          + instruction_data.len() // instruction data
          + instruction_data.len() // instruction data
          + size_of::<Pubkey>(); // program id
          + size_of::<Pubkey>(); // program id
 
 
-    let mut s = Serializer::new(size, MM_INPUT_START, true, direct_mapping);
+    let mut s = Serializer::new(
+        size,
+        MM_INPUT_START,
+        true,
+        stricter_abi_and_runtime_constraints,
+        account_data_direct_mapping,
+    );
 
 
     let mut accounts_metadata: Vec<SerializedAccountMetadata> = Vec::with_capacity(accounts.len());
     let mut accounts_metadata: Vec<SerializedAccountMetadata> = Vec::with_capacity(accounts.len());
     s.write::<u64>((accounts.len() as u64).to_le());
     s.write::<u64>((accounts.len() as u64).to_le());
@@ -367,7 +419,8 @@ fn serialize_parameters_unaligned(
 fn deserialize_parameters_unaligned<I: IntoIterator<Item = usize>>(
 fn deserialize_parameters_unaligned<I: IntoIterator<Item = usize>>(
     transaction_context: &TransactionContext,
     transaction_context: &TransactionContext,
     instruction_context: &InstructionContext,
     instruction_context: &InstructionContext,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
     buffer: &[u8],
     buffer: &[u8],
     account_lengths: I,
     account_lengths: I,
 ) -> Result<(), InstructionError> {
 ) -> Result<(), InstructionError> {
@@ -396,7 +449,7 @@ fn deserialize_parameters_unaligned<I: IntoIterator<Item = usize>>(
             }
             }
             start += size_of::<u64>() // lamports
             start += size_of::<u64>() // lamports
                 + size_of::<u64>(); // data length
                 + size_of::<u64>(); // data length
-            if !direct_mapping {
+            if !stricter_abi_and_runtime_constraints {
                 let data = buffer
                 let data = buffer
                     .get(start..start + pre_len)
                     .get(start..start + pre_len)
                     .ok_or(InstructionError::InvalidArgument)?;
                     .ok_or(InstructionError::InvalidArgument)?;
@@ -406,10 +459,18 @@ fn deserialize_parameters_unaligned<I: IntoIterator<Item = usize>>(
                     Err(err) if borrowed_account.get_data() != data => return Err(err),
                     Err(err) if borrowed_account.get_data() != data => return Err(err),
                     _ => {}
                     _ => {}
                 }
                 }
-                start += pre_len; // data
+            } else if !account_data_direct_mapping && borrowed_account.can_data_be_changed().is_ok()
+            {
+                let data = buffer
+                    .get(start..start + pre_len)
+                    .ok_or(InstructionError::InvalidArgument)?;
+                borrowed_account.set_data_from_slice(data)?;
             } else if borrowed_account.get_data().len() != pre_len {
             } else if borrowed_account.get_data().len() != pre_len {
                 borrowed_account.set_data_length(pre_len)?;
                 borrowed_account.set_data_length(pre_len)?;
             }
             }
+            if !(stricter_abi_and_runtime_constraints && account_data_direct_mapping) {
+                start += pre_len; // data
+            }
             start += size_of::<Pubkey>() // owner
             start += size_of::<Pubkey>() // owner
                 + size_of::<u8>() // executable
                 + size_of::<u8>() // executable
                 + size_of::<u64>(); // rent_epoch
                 + size_of::<u64>(); // rent_epoch
@@ -422,7 +483,8 @@ fn serialize_parameters_aligned(
     accounts: Vec<SerializeAccount>,
     accounts: Vec<SerializeAccount>,
     instruction_data: &[u8],
     instruction_data: &[u8],
     program_id: &Pubkey,
     program_id: &Pubkey,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
     mask_out_rent_epoch_in_vm_serialization: bool,
     mask_out_rent_epoch_in_vm_serialization: bool,
 ) -> Result<
 ) -> Result<
     (
     (
@@ -450,7 +512,7 @@ fn serialize_parameters_aligned(
                 + size_of::<u64>()  // lamports
                 + size_of::<u64>()  // lamports
                 + size_of::<u64>()  // data len
                 + size_of::<u64>()  // data len
                 + size_of::<u64>(); // rent epoch
                 + size_of::<u64>(); // rent epoch
-                if !direct_mapping {
+                if !(stricter_abi_and_runtime_constraints && account_data_direct_mapping) {
                     size += data_len
                     size += data_len
                         + MAX_PERMITTED_DATA_INCREASE
                         + MAX_PERMITTED_DATA_INCREASE
                         + (data_len as *const u8).align_offset(BPF_ALIGN_OF_U128);
                         + (data_len as *const u8).align_offset(BPF_ALIGN_OF_U128);
@@ -464,7 +526,13 @@ fn serialize_parameters_aligned(
     + instruction_data.len()
     + instruction_data.len()
     + size_of::<Pubkey>(); // program id;
     + size_of::<Pubkey>(); // program id;
 
 
-    let mut s = Serializer::new(size, MM_INPUT_START, false, direct_mapping);
+    let mut s = Serializer::new(
+        size,
+        MM_INPUT_START,
+        false,
+        stricter_abi_and_runtime_constraints,
+        account_data_direct_mapping,
+    );
 
 
     // Serialize into the buffer
     // Serialize into the buffer
     s.write::<u64>((accounts.len() as u64).to_le());
     s.write::<u64>((accounts.len() as u64).to_le());
@@ -514,7 +582,8 @@ fn serialize_parameters_aligned(
 fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
 fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
     transaction_context: &TransactionContext,
     transaction_context: &TransactionContext,
     instruction_context: &InstructionContext,
     instruction_context: &InstructionContext,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
     buffer: &[u8],
     buffer: &[u8],
     account_lengths: I,
     account_lengths: I,
 ) -> Result<(), InstructionError> {
 ) -> Result<(), InstructionError> {
@@ -562,7 +631,7 @@ fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
             {
             {
                 return Err(InstructionError::InvalidRealloc);
                 return Err(InstructionError::InvalidRealloc);
             }
             }
-            if !direct_mapping {
+            if !stricter_abi_and_runtime_constraints {
                 let data = buffer
                 let data = buffer
                     .get(start..start + post_len)
                     .get(start..start + post_len)
                     .ok_or(InstructionError::InvalidArgument)?;
                     .ok_or(InstructionError::InvalidArgument)?;
@@ -572,10 +641,16 @@ fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
                     Err(err) if borrowed_account.get_data() != data => return Err(err),
                     Err(err) if borrowed_account.get_data() != data => return Err(err),
                     _ => {}
                     _ => {}
                 }
                 }
+            } else if !account_data_direct_mapping && borrowed_account.can_data_be_changed().is_ok()
+            {
+                let data = buffer
+                    .get(start..start + post_len)
+                    .ok_or(InstructionError::InvalidArgument)?;
+                borrowed_account.set_data_from_slice(data)?;
             } else if borrowed_account.get_data().len() != post_len {
             } else if borrowed_account.get_data().len() != post_len {
                 borrowed_account.set_data_length(post_len)?;
                 borrowed_account.set_data_length(post_len)?;
             }
             }
-            start += if !direct_mapping {
+            start += if !(stricter_abi_and_runtime_constraints && account_data_direct_mapping) {
                 let alignment_offset = (pre_len as *const u8).align_offset(BPF_ALIGN_OF_U128);
                 let alignment_offset = (pre_len as *const u8).align_offset(BPF_ALIGN_OF_U128);
                 pre_len // data
                 pre_len // data
                     .saturating_add(MAX_PERMITTED_DATA_INCREASE) // realloc padding
                     .saturating_add(MAX_PERMITTED_DATA_INCREASE) // realloc padding
@@ -649,7 +724,7 @@ mod tests {
             name: &'static str,
             name: &'static str,
         }
         }
 
 
-        for direct_mapping in [false] {
+        for stricter_abi_and_runtime_constraints in [false, true] {
             for TestCase {
             for TestCase {
                 num_ix_accounts,
                 num_ix_accounts,
                 append_dup_account,
                 append_dup_account,
@@ -728,8 +803,9 @@ mod tests {
                 let serialization_result = serialize_parameters(
                 let serialization_result = serialize_parameters(
                     invoke_context.transaction_context,
                     invoke_context.transaction_context,
                     instruction_context,
                     instruction_context,
-                    direct_mapping,
-                    true, // mask_out_rent_epoch_in_vm_serialization
+                    stricter_abi_and_runtime_constraints,
+                    false, // account_data_direct_mapping
+                    true,  // mask_out_rent_epoch_in_vm_serialization
                 );
                 );
                 assert_eq!(
                 assert_eq!(
                     serialization_result.as_ref().err(),
                     serialization_result.as_ref().err(),
@@ -744,7 +820,7 @@ mod tests {
                 let mut serialized_regions = concat_regions(&regions);
                 let mut serialized_regions = concat_regions(&regions);
                 let (de_program_id, de_accounts, de_instruction_data) = unsafe {
                 let (de_program_id, de_accounts, de_instruction_data) = unsafe {
                     deserialize(
                     deserialize(
-                        if !direct_mapping {
+                        if !stricter_abi_and_runtime_constraints {
                             serialized.as_slice_mut()
                             serialized.as_slice_mut()
                         } else {
                         } else {
                             serialized_regions.as_slice_mut()
                             serialized_regions.as_slice_mut()
@@ -777,7 +853,7 @@ mod tests {
 
 
     #[test]
     #[test]
     fn test_serialize_parameters() {
     fn test_serialize_parameters() {
-        for direct_mapping in [false, true] {
+        for stricter_abi_and_runtime_constraints in [false, true] {
             let program_id = solana_pubkey::new_rand();
             let program_id = solana_pubkey::new_rand();
             let transaction_accounts = vec![
             let transaction_accounts = vec![
                 (
                 (
@@ -872,18 +948,19 @@ mod tests {
             let (mut serialized, regions, accounts_metadata) = serialize_parameters(
             let (mut serialized, regions, accounts_metadata) = serialize_parameters(
                 invoke_context.transaction_context,
                 invoke_context.transaction_context,
                 instruction_context,
                 instruction_context,
-                direct_mapping,
-                true, // mask_out_rent_epoch_in_vm_serialization
+                stricter_abi_and_runtime_constraints,
+                false, // account_data_direct_mapping
+                true,  // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();
 
 
             let mut serialized_regions = concat_regions(&regions);
             let mut serialized_regions = concat_regions(&regions);
-            if !direct_mapping {
+            if !stricter_abi_and_runtime_constraints {
                 assert_eq!(serialized.as_slice(), serialized_regions.as_slice());
                 assert_eq!(serialized.as_slice(), serialized_regions.as_slice());
             }
             }
             let (de_program_id, de_accounts, de_instruction_data) = unsafe {
             let (de_program_id, de_accounts, de_instruction_data) = unsafe {
                 deserialize(
                 deserialize(
-                    if !direct_mapping {
+                    if !stricter_abi_and_runtime_constraints {
                         serialized.as_slice_mut()
                         serialized.as_slice_mut()
                     } else {
                     } else {
                         serialized_regions.as_slice_mut()
                         serialized_regions.as_slice_mut()
@@ -932,7 +1009,8 @@ mod tests {
             deserialize_parameters(
             deserialize_parameters(
                 invoke_context.transaction_context,
                 invoke_context.transaction_context,
                 instruction_context,
                 instruction_context,
-                direct_mapping,
+                stricter_abi_and_runtime_constraints,
+                false, // account_data_direct_mapping
                 serialized.as_slice(),
                 serialized.as_slice(),
                 &accounts_metadata,
                 &accounts_metadata,
             )
             )
@@ -965,15 +1043,16 @@ mod tests {
             let (mut serialized, regions, account_lengths) = serialize_parameters(
             let (mut serialized, regions, account_lengths) = serialize_parameters(
                 invoke_context.transaction_context,
                 invoke_context.transaction_context,
                 instruction_context,
                 instruction_context,
-                direct_mapping,
-                true, // mask_out_rent_epoch_in_vm_serialization
+                stricter_abi_and_runtime_constraints,
+                false, // account_data_direct_mapping
+                true,  // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();
             let mut serialized_regions = concat_regions(&regions);
             let mut serialized_regions = concat_regions(&regions);
 
 
             let (de_program_id, de_accounts, de_instruction_data) = unsafe {
             let (de_program_id, de_accounts, de_instruction_data) = unsafe {
                 deserialize_unaligned(
                 deserialize_unaligned(
-                    if !direct_mapping {
+                    if !stricter_abi_and_runtime_constraints {
                         serialized.as_slice_mut()
                         serialized.as_slice_mut()
                     } else {
                     } else {
                         serialized_regions.as_slice_mut()
                         serialized_regions.as_slice_mut()
@@ -1004,7 +1083,8 @@ mod tests {
             deserialize_parameters(
             deserialize_parameters(
                 invoke_context.transaction_context,
                 invoke_context.transaction_context,
                 instruction_context,
                 instruction_context,
-                direct_mapping,
+                stricter_abi_and_runtime_constraints,
+                false, // account_data_direct_mapping
                 serialized.as_slice(),
                 serialized.as_slice(),
                 &account_lengths,
                 &account_lengths,
             )
             )
@@ -1119,6 +1199,7 @@ mod tests {
                 invoke_context.transaction_context,
                 invoke_context.transaction_context,
                 instruction_context,
                 instruction_context,
                 true,
                 true,
+                false, // account_data_direct_mapping
                 mask_out_rent_epoch_in_vm_serialization,
                 mask_out_rent_epoch_in_vm_serialization,
             )
             )
             .unwrap();
             .unwrap();
@@ -1164,6 +1245,7 @@ mod tests {
                 invoke_context.transaction_context,
                 invoke_context.transaction_context,
                 instruction_context,
                 instruction_context,
                 true,
                 true,
+                false, // account_data_direct_mapping
                 mask_out_rent_epoch_in_vm_serialization,
                 mask_out_rent_epoch_in_vm_serialization,
             )
             )
             .unwrap();
             .unwrap();
@@ -1411,7 +1493,7 @@ mod tests {
             regions,
             regions,
             &config,
             &config,
             SBPFVersion::V3,
             SBPFVersion::V3,
-            transaction_context.access_violation_handler(),
+            transaction_context.access_violation_handler(true, true),
         )
         )
         .unwrap();
         .unwrap();
 
 

+ 2 - 1
program-test/src/lib.rs

@@ -133,7 +133,8 @@ pub fn invoke_builtin_function(
     let (mut parameter_bytes, _regions, _account_lengths) = serialize_parameters(
     let (mut parameter_bytes, _regions, _account_lengths) = serialize_parameters(
         transaction_context,
         transaction_context,
         instruction_context,
         instruction_context,
-        false, // direct_mapping // There is no VM so direct mapping can not be implemented here
+        false, // There is no VM so stricter_abi_and_runtime_constraints can not be implemented here
+        false, // There is no VM so account_data_direct_mapping can not be implemented here
         mask_out_rent_epoch_in_vm_serialization,
         mask_out_rent_epoch_in_vm_serialization,
     )?;
     )?;
 
 

+ 12 - 6
programs/bpf_loader/benches/serialization.rs

@@ -123,7 +123,8 @@ fn bench_serialize_unaligned(c: &mut Criterion) {
             let _ = serialize_parameters(
             let _ = serialize_parameters(
                 &transaction_context,
                 &transaction_context,
                 instruction_context,
                 instruction_context,
-                true, // direct_mapping
+                true, // stricter_abi_and_runtime_constraints
+                true, // account_data_direct_mapping
                 true, // mask_out_rent_epoch_in_vm_serialization
                 true, // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();
@@ -141,7 +142,8 @@ fn bench_serialize_unaligned_copy_account_data(c: &mut Criterion) {
             let _ = serialize_parameters(
             let _ = serialize_parameters(
                 &transaction_context,
                 &transaction_context,
                 instruction_context,
                 instruction_context,
-                false, // direct_mapping
+                false, // stricter_abi_and_runtime_constraints
+                false, // account_data_direct_mapping
                 true,  // mask_out_rent_epoch_in_vm_serialization
                 true,  // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();
@@ -160,7 +162,8 @@ fn bench_serialize_aligned(c: &mut Criterion) {
             let _ = serialize_parameters(
             let _ = serialize_parameters(
                 &transaction_context,
                 &transaction_context,
                 instruction_context,
                 instruction_context,
-                true, // direct_mapping
+                true, // stricter_abi_and_runtime_constraints
+                true, // account_data_direct_mapping
                 true, // mask_out_rent_epoch_in_vm_serialization
                 true, // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();
@@ -179,7 +182,8 @@ fn bench_serialize_aligned_copy_account_data(c: &mut Criterion) {
             let _ = serialize_parameters(
             let _ = serialize_parameters(
                 &transaction_context,
                 &transaction_context,
                 instruction_context,
                 instruction_context,
-                false, // direct_mapping
+                false, // stricter_abi_and_runtime_constraints
+                false, // account_data_direct_mapping
                 true,  // mask_out_rent_epoch_in_vm_serialization
                 true,  // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();
@@ -198,7 +202,8 @@ fn bench_serialize_unaligned_max_accounts(c: &mut Criterion) {
             let _ = serialize_parameters(
             let _ = serialize_parameters(
                 &transaction_context,
                 &transaction_context,
                 instruction_context,
                 instruction_context,
-                true, // direct_mapping
+                true, // stricter_abi_and_runtime_constraints
+                true, // account_data_direct_mapping
                 true, // mask_out_rent_epoch_in_vm_serialization
                 true, // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();
@@ -217,7 +222,8 @@ fn bench_serialize_aligned_max_accounts(c: &mut Criterion) {
             let _ = serialize_parameters(
             let _ = serialize_parameters(
                 &transaction_context,
                 &transaction_context,
                 instruction_context,
                 instruction_context,
-                true, // direct_mapping
+                true, // stricter_abi_and_runtime_constraints
+                true, // account_data_direct_mapping
                 true, // mask_out_rent_epoch_in_vm_serialization
                 true, // mask_out_rent_epoch_in_vm_serialization
             )
             )
             .unwrap();
             .unwrap();

+ 25 - 10
programs/bpf_loader/src/lib.rs

@@ -269,6 +269,10 @@ fn create_vm<'a, 'b>(
         heap,
         heap,
         regions,
         regions,
         invoke_context.transaction_context,
         invoke_context.transaction_context,
+        invoke_context
+            .get_feature_set()
+            .stricter_abi_and_runtime_constraints,
+        invoke_context.account_data_direct_mapping,
     )?;
     )?;
     invoke_context.set_syscall_context(SyscallContext {
     invoke_context.set_syscall_context(SyscallContext {
         allocator: BpfAllocator::new(heap_size as u64),
         allocator: BpfAllocator::new(heap_size as u64),
@@ -322,6 +326,8 @@ fn create_memory_mapping<'a, 'b, C: ContextObject>(
     heap: &'b mut [u8],
     heap: &'b mut [u8],
     additional_regions: Vec<MemoryRegion>,
     additional_regions: Vec<MemoryRegion>,
     transaction_context: &TransactionContext,
     transaction_context: &TransactionContext,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
 ) -> Result<MemoryMapping<'a>, Box<dyn std::error::Error>> {
 ) -> Result<MemoryMapping<'a>, Box<dyn std::error::Error>> {
     let config = executable.get_config();
     let config = executable.get_config();
     let sbpf_version = executable.get_sbpf_version();
     let sbpf_version = executable.get_sbpf_version();
@@ -346,7 +352,10 @@ fn create_memory_mapping<'a, 'b, C: ContextObject>(
         regions,
         regions,
         config,
         config,
         sbpf_version,
         sbpf_version,
-        transaction_context.access_violation_handler(),
+        transaction_context.access_violation_handler(
+            stricter_abi_and_runtime_constraints,
+            account_data_direct_mapping,
+        ),
     )?)
     )?)
 }
 }
 
 
@@ -1587,9 +1596,9 @@ fn execute<'a, 'b: 'a>(
     let use_jit = false;
     let use_jit = false;
     #[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
     #[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
     let use_jit = executable.get_compiled_program().is_some();
     let use_jit = executable.get_compiled_program().is_some();
-    let direct_mapping = invoke_context
+    let stricter_abi_and_runtime_constraints = invoke_context
         .get_feature_set()
         .get_feature_set()
-        .bpf_account_data_direct_mapping;
+        .stricter_abi_and_runtime_constraints;
     let mask_out_rent_epoch_in_vm_serialization = invoke_context
     let mask_out_rent_epoch_in_vm_serialization = invoke_context
         .get_feature_set()
         .get_feature_set()
         .mask_out_rent_epoch_in_vm_serialization;
         .mask_out_rent_epoch_in_vm_serialization;
@@ -1598,7 +1607,8 @@ fn execute<'a, 'b: 'a>(
     let (parameter_bytes, regions, accounts_metadata) = serialization::serialize_parameters(
     let (parameter_bytes, regions, accounts_metadata) = serialization::serialize_parameters(
         invoke_context.transaction_context,
         invoke_context.transaction_context,
         instruction_context,
         instruction_context,
-        direct_mapping,
+        stricter_abi_and_runtime_constraints,
+        invoke_context.account_data_direct_mapping,
         mask_out_rent_epoch_in_vm_serialization,
         mask_out_rent_epoch_in_vm_serialization,
     )?;
     )?;
     serialize_time.stop();
     serialize_time.stop();
@@ -1679,7 +1689,7 @@ fn execute<'a, 'b: 'a>(
                     invoke_context.consume(invoke_context.get_remaining());
                     invoke_context.consume(invoke_context.get_remaining());
                 }
                 }
 
 
-                if direct_mapping {
+                if stricter_abi_and_runtime_constraints {
                     if let EbpfError::SyscallError(err) = error {
                     if let EbpfError::SyscallError(err) = error {
                         error = err
                         error = err
                             .downcast::<EbpfError>()
                             .downcast::<EbpfError>()
@@ -1689,7 +1699,7 @@ fn execute<'a, 'b: 'a>(
                     if let EbpfError::AccessViolation(access_type, vm_addr, len, _section_name) =
                     if let EbpfError::AccessViolation(access_type, vm_addr, len, _section_name) =
                         error
                         error
                     {
                     {
-                        // If direct_mapping is enabled and a program tries to write to a readonly
+                        // If stricter_abi_and_runtime_constraints is enabled and a program tries to write to a readonly
                         // region we'll get a memory access violation. Map it to a more specific
                         // region we'll get a memory access violation. Map it to a more specific
                         // error so it's easier for developers to see what happened.
                         // error so it's easier for developers to see what happened.
                         if let Some((instruction_account_index, vm_addr_range)) =
                         if let Some((instruction_account_index, vm_addr_range)) =
@@ -1757,14 +1767,15 @@ fn execute<'a, 'b: 'a>(
     fn deserialize_parameters(
     fn deserialize_parameters(
         invoke_context: &mut InvokeContext,
         invoke_context: &mut InvokeContext,
         parameter_bytes: &[u8],
         parameter_bytes: &[u8],
-        direct_mapping: bool,
+        stricter_abi_and_runtime_constraints: bool,
     ) -> Result<(), InstructionError> {
     ) -> Result<(), InstructionError> {
         serialization::deserialize_parameters(
         serialization::deserialize_parameters(
             invoke_context.transaction_context,
             invoke_context.transaction_context,
             invoke_context
             invoke_context
                 .transaction_context
                 .transaction_context
                 .get_current_instruction_context()?,
                 .get_current_instruction_context()?,
-            direct_mapping,
+            stricter_abi_and_runtime_constraints,
+            invoke_context.account_data_direct_mapping,
             parameter_bytes,
             parameter_bytes,
             &invoke_context.get_syscall_context()?.accounts_metadata,
             &invoke_context.get_syscall_context()?.accounts_metadata,
         )
         )
@@ -1772,8 +1783,12 @@ fn execute<'a, 'b: 'a>(
 
 
     let mut deserialize_time = Measure::start("deserialize");
     let mut deserialize_time = Measure::start("deserialize");
     let execute_or_deserialize_result = execution_result.and_then(|_| {
     let execute_or_deserialize_result = execution_result.and_then(|_| {
-        deserialize_parameters(invoke_context, parameter_bytes.as_slice(), direct_mapping)
-            .map_err(|error| Box::new(error) as Box<dyn std::error::Error>)
+        deserialize_parameters(
+            invoke_context,
+            parameter_bytes.as_slice(),
+            stricter_abi_and_runtime_constraints,
+        )
+        .map_err(|error| Box::new(error) as Box<dyn std::error::Error>)
     });
     });
     deserialize_time.stop();
     deserialize_time.stop();
 
 

+ 10 - 8
programs/sbf/benches/bpf_loader.rs

@@ -224,9 +224,9 @@ fn bench_create_vm(bencher: &mut Bencher) {
     const BUDGET: u64 = 200_000;
     const BUDGET: u64 = 200_000;
     invoke_context.mock_set_remaining(BUDGET);
     invoke_context.mock_set_remaining(BUDGET);
 
 
-    let direct_mapping = invoke_context
+    let stricter_abi_and_runtime_constraints = invoke_context
         .get_feature_set()
         .get_feature_set()
-        .bpf_account_data_direct_mapping;
+        .stricter_abi_and_runtime_constraints;
     let raise_cpi_nesting_limit_to_8 = invoke_context
     let raise_cpi_nesting_limit_to_8 = invoke_context
         .get_feature_set()
         .get_feature_set()
         .raise_cpi_nesting_limit_to_8;
         .raise_cpi_nesting_limit_to_8;
@@ -249,8 +249,9 @@ fn bench_create_vm(bencher: &mut Bencher) {
             .transaction_context
             .transaction_context
             .get_current_instruction_context()
             .get_current_instruction_context()
             .unwrap(),
             .unwrap(),
-        direct_mapping,
-        true, // mask_out_rent_epoch_in_vm_serialization
+        stricter_abi_and_runtime_constraints,
+        false, // account_data_direct_mapping
+        true,  // mask_out_rent_epoch_in_vm_serialization
     )
     )
     .unwrap();
     .unwrap();
 
 
@@ -273,9 +274,9 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
     const BUDGET: u64 = 200_000;
     const BUDGET: u64 = 200_000;
     invoke_context.mock_set_remaining(BUDGET);
     invoke_context.mock_set_remaining(BUDGET);
 
 
-    let direct_mapping = invoke_context
+    let stricter_abi_and_runtime_constraints = invoke_context
         .get_feature_set()
         .get_feature_set()
-        .bpf_account_data_direct_mapping;
+        .stricter_abi_and_runtime_constraints;
 
 
     // Serialize account data
     // Serialize account data
     let (_serialized, regions, account_lengths) = serialize_parameters(
     let (_serialized, regions, account_lengths) = serialize_parameters(
@@ -284,8 +285,9 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
             .transaction_context
             .transaction_context
             .get_current_instruction_context()
             .get_current_instruction_context()
             .unwrap(),
             .unwrap(),
-        direct_mapping,
-        true, // mask_out_rent_epoch_in_vm_serialization
+        stricter_abi_and_runtime_constraints,
+        false, // account_data_direct_mapping
+        true,  // mask_out_rent_epoch_in_vm_serialization
     )
     )
     .unwrap();
     .unwrap();
 
 

+ 6 - 6
programs/sbf/rust/deprecated_loader/src/lib.rs

@@ -74,9 +74,9 @@ fn process_instruction(
             let expected = {
             let expected = {
                 let data = &instruction_data[1..];
                 let data = &instruction_data[1..];
                 let prev_len = account.data_len();
                 let prev_len = account.data_len();
-                // when direct mapping is off, this will accidentally clobber
+                // when stricter_abi_and_runtime_constraints is off, this will accidentally clobber
                 // whatever comes after the data slice (owner, executable, rent
                 // whatever comes after the data slice (owner, executable, rent
-                // epoch etc). When direct mapping is on, you get an
+                // epoch etc). When stricter_abi_and_runtime_constraints is on, you get an
                 // InvalidRealloc error.
                 // InvalidRealloc error.
                 account.resize(prev_len + data.len())?;
                 account.resize(prev_len + data.len())?;
                 account.data.borrow_mut()[prev_len..].copy_from_slice(data);
                 account.data.borrow_mut()[prev_len..].copy_from_slice(data);
@@ -144,7 +144,7 @@ fn process_instruction(
             let realloc_program_id = accounts[REALLOC_PROGRAM_INDEX].key;
             let realloc_program_id = accounts[REALLOC_PROGRAM_INDEX].key;
             let realloc_program_owner = accounts[REALLOC_PROGRAM_INDEX].owner;
             let realloc_program_owner = accounts[REALLOC_PROGRAM_INDEX].owner;
             let invoke_program_id = accounts[INVOKE_PROGRAM_INDEX].key;
             let invoke_program_id = accounts[INVOKE_PROGRAM_INDEX].key;
-            let direct_mapping = instruction_data[1];
+            let stricter_abi_and_runtime_constraints = instruction_data[1];
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             let prev_len = account.data_len();
             let prev_len = account.data_len();
             let expected = account.data.borrow()[..new_len].to_vec();
             let expected = account.data.borrow()[..new_len].to_vec();
@@ -167,7 +167,7 @@ fn process_instruction(
             // deserialize_parameters_unaligned predates realloc support, and
             // deserialize_parameters_unaligned predates realloc support, and
             // hardcodes the account data length to the original length.
             // hardcodes the account data length to the original length.
             if !solana_program::bpf_loader_deprecated::check_id(realloc_program_owner)
             if !solana_program::bpf_loader_deprecated::check_id(realloc_program_owner)
-                && direct_mapping == 0
+                && stricter_abi_and_runtime_constraints == 0
             {
             {
                 assert_eq!(&*account.data.borrow(), &expected);
                 assert_eq!(&*account.data.borrow(), &expected);
                 assert_eq!(
                 assert_eq!(
@@ -208,7 +208,7 @@ fn process_instruction(
             };
             };
 
 
             let mut expected = account.data.borrow().to_vec();
             let mut expected = account.data.borrow().to_vec();
-            let direct_mapping = instruction_data[1];
+            let stricter_abi_and_runtime_constraints = instruction_data[1];
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             expected.extend_from_slice(&instruction_data[10..]);
             expected.extend_from_slice(&instruction_data[10..]);
             let mut instruction_data =
             let mut instruction_data =
@@ -228,7 +228,7 @@ fn process_instruction(
             .unwrap();
             .unwrap();
 
 
             assert_eq!(*account.data.borrow(), &prev_data[..new_len]);
             assert_eq!(*account.data.borrow(), &prev_data[..new_len]);
-            if direct_mapping == 0 {
+            if stricter_abi_and_runtime_constraints == 0 {
                 assert_eq!(
                 assert_eq!(
                     unsafe {
                     unsafe {
                         std::slice::from_raw_parts(
                         std::slice::from_raw_parts(

+ 8 - 6
programs/sbf/rust/invoke/src/lib.rs

@@ -877,7 +877,7 @@ fn process_instruction<'a>(
                         // TEST_FORBID_LEN_UPDATE_AFTER_OWNERSHIP_CHANGE_MOVING_DATA_POINTER
                         // TEST_FORBID_LEN_UPDATE_AFTER_OWNERSHIP_CHANGE_MOVING_DATA_POINTER
                         // is that we don't move the data pointer past the
                         // is that we don't move the data pointer past the
                         // RcBox. This is needed to avoid the "Invalid account
                         // RcBox. This is needed to avoid the "Invalid account
-                        // info pointer" check when direct mapping is enabled.
+                        // info pointer" check when stricter_abi_and_runtime_constraints is enabled.
                         // This also means we don't need to update the
                         // This also means we don't need to update the
                         // serialized len like we do in the other test.
                         // serialized len like we do in the other test.
                         value: RefCell::new(slice::from_raw_parts_mut(
                         value: RefCell::new(slice::from_raw_parts_mut(
@@ -1032,7 +1032,7 @@ fn process_instruction<'a>(
             let realloc_program_id = accounts[REALLOC_PROGRAM_INDEX].key;
             let realloc_program_id = accounts[REALLOC_PROGRAM_INDEX].key;
             let realloc_program_owner = accounts[REALLOC_PROGRAM_INDEX].owner;
             let realloc_program_owner = accounts[REALLOC_PROGRAM_INDEX].owner;
             let invoke_program_id = accounts[INVOKE_PROGRAM_INDEX].key;
             let invoke_program_id = accounts[INVOKE_PROGRAM_INDEX].key;
-            let direct_mapping = instruction_data[1];
+            let stricter_abi_and_runtime_constraints = instruction_data[1];
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             let prev_len = account.data_len();
             let prev_len = account.data_len();
             let expected = account.data.borrow()[..new_len].to_vec();
             let expected = account.data.borrow()[..new_len].to_vec();
@@ -1054,7 +1054,9 @@ fn process_instruction<'a>(
 
 
             // deserialize_parameters_unaligned predates realloc support, and
             // deserialize_parameters_unaligned predates realloc support, and
             // hardcodes the account data length to the original length.
             // hardcodes the account data length to the original length.
-            if !bpf_loader_deprecated::check_id(realloc_program_owner) && direct_mapping == 0 {
+            if !bpf_loader_deprecated::check_id(realloc_program_owner)
+                && stricter_abi_and_runtime_constraints == 0
+            {
                 assert_eq!(&*account.data.borrow(), &expected);
                 assert_eq!(&*account.data.borrow(), &expected);
                 assert_eq!(
                 assert_eq!(
                     unsafe {
                     unsafe {
@@ -1093,7 +1095,7 @@ fn process_instruction<'a>(
             };
             };
 
 
             let mut expected = account.data.borrow().to_vec();
             let mut expected = account.data.borrow().to_vec();
-            let direct_mapping = instruction_data[1];
+            let stricter_abi_and_runtime_constraints = instruction_data[1];
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             let new_len = usize::from_le_bytes(instruction_data[2..10].try_into().unwrap());
             expected.extend_from_slice(&instruction_data[10..]);
             expected.extend_from_slice(&instruction_data[10..]);
             let mut instruction_data =
             let mut instruction_data =
@@ -1113,7 +1115,7 @@ fn process_instruction<'a>(
             .unwrap();
             .unwrap();
 
 
             assert_eq!(*account.data.borrow(), &prev_data[..new_len]);
             assert_eq!(*account.data.borrow(), &prev_data[..new_len]);
-            if direct_mapping == 0 {
+            if stricter_abi_and_runtime_constraints == 0 {
                 assert_eq!(
                 assert_eq!(
                     unsafe {
                     unsafe {
                         slice::from_raw_parts(
                         slice::from_raw_parts(
@@ -1302,7 +1304,7 @@ fn process_instruction<'a>(
             }
             }
 
 
             if !invoke_struction.is_empty() {
             if !invoke_struction.is_empty() {
-                // Invoke another program. With direct mapping, before CPI the callee will update the accounts (incl resizing)
+                // Invoke another program. With stricter_abi_and_runtime_constraints, before CPI the callee will update the accounts (incl resizing)
                 // so the pointer may change.
                 // so the pointer may change.
                 let invoked_program_id = accounts[INVOKED_PROGRAM_INDEX].key;
                 let invoked_program_id = accounts[INVOKED_PROGRAM_INDEX].key;
 
 

+ 56 - 56
programs/sbf/tests/programs.rs

@@ -2445,13 +2445,13 @@ fn test_program_sbf_realloc() {
 
 
     let mint_pubkey = mint_keypair.pubkey();
     let mint_pubkey = mint_keypair.pubkey();
     let signer = &[&mint_keypair];
     let signer = &[&mint_keypair];
-    for direct_mapping in [false, true] {
+    for stricter_abi_and_runtime_constraints in [false, true] {
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         // by default test banks have all features enabled, so we only need to
         // by default test banks have all features enabled, so we only need to
         // disable when needed
         // disable when needed
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let mut bank_client = BankClient::new_shared(bank.clone());
         let mut bank_client = BankClient::new_shared(bank.clone());
@@ -3738,7 +3738,7 @@ fn test_program_sbf_inner_instruction_alignment_checks() {
 fn test_cpi_account_ownership_writability() {
 fn test_cpi_account_ownership_writability() {
     solana_logger::setup();
     solana_logger::setup();
 
 
-    for direct_mapping in [false, true] {
+    for stricter_abi_and_runtime_constraints in [false, true] {
         let GenesisConfigInfo {
         let GenesisConfigInfo {
             genesis_config,
             genesis_config,
             mint_keypair,
             mint_keypair,
@@ -3747,8 +3747,8 @@ fn test_cpi_account_ownership_writability() {
 
 
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut feature_set = FeatureSet::all_enabled();
         let mut feature_set = FeatureSet::all_enabled();
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
 
 
         bank.feature_set = Arc::new(feature_set);
         bank.feature_set = Arc::new(feature_set);
@@ -3815,7 +3815,7 @@ fn test_cpi_account_ownership_writability() {
 
 
                 let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
                 let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 
 
-                if (byte_index as usize) < account_size || direct_mapping {
+                if (byte_index as usize) < account_size || stricter_abi_and_runtime_constraints {
                     assert_eq!(
                     assert_eq!(
                         result.unwrap_err().unwrap(),
                         result.unwrap_err().unwrap(),
                         TransactionError::InstructionError(
                         TransactionError::InstructionError(
@@ -3824,7 +3824,7 @@ fn test_cpi_account_ownership_writability() {
                         )
                         )
                     );
                     );
                 } else {
                 } else {
-                    // without direct mapping, changes to the realloc padding
+                    // without stricter_abi_and_runtime_constraints, changes to the realloc padding
                     // outside the account length are ignored
                     // outside the account length are ignored
                     assert!(result.is_ok(), "{result:?}");
                     assert!(result.is_ok(), "{result:?}");
                 }
                 }
@@ -3832,11 +3832,11 @@ fn test_cpi_account_ownership_writability() {
         }
         }
         // Test that the CPI code that updates `ref_to_len_in_vm` fails if we
         // Test that the CPI code that updates `ref_to_len_in_vm` fails if we
         // make it write to an invalid location. This is the first variant which
         // make it write to an invalid location. This is the first variant which
-        // correctly triggers ExternalAccountDataModified when direct mapping is
-        // disabled. When direct mapping is enabled this tests fails early
+        // correctly triggers ExternalAccountDataModified when stricter_abi_and_runtime_constraints is
+        // disabled. When stricter_abi_and_runtime_constraints is enabled this tests fails early
         // because we move the account data pointer.
         // because we move the account data pointer.
         // TEST_FORBID_LEN_UPDATE_AFTER_OWNERSHIP_CHANGE is able to make more
         // TEST_FORBID_LEN_UPDATE_AFTER_OWNERSHIP_CHANGE is able to make more
-        // progress when direct mapping is on.
+        // progress when stricter_abi_and_runtime_constraints is on.
         let account = AccountSharedData::new(42, 0, &invoke_program_id);
         let account = AccountSharedData::new(42, 0, &invoke_program_id);
         bank.store_account(&account_keypair.pubkey(), &account);
         bank.store_account(&account_keypair.pubkey(), &account);
         let instruction_data = vec![
         let instruction_data = vec![
@@ -3853,8 +3853,8 @@ fn test_cpi_account_ownership_writability() {
         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
         assert_eq!(
         assert_eq!(
             result.unwrap_err().unwrap(),
             result.unwrap_err().unwrap(),
-            if direct_mapping {
-                // We move the data pointer, direct mapping doesn't allow it
+            if stricter_abi_and_runtime_constraints {
+                // We move the data pointer, stricter_abi_and_runtime_constraints doesn't allow it
                 // anymore so it errors out earlier. See
                 // anymore so it errors out earlier. See
                 // test_cpi_invalid_account_info_pointers.
                 // test_cpi_invalid_account_info_pointers.
                 TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
                 TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
@@ -3873,7 +3873,7 @@ fn test_cpi_account_ownership_writability() {
 
 
         for target_account in [1, account_metas.len() as u8 - 1] {
         for target_account in [1, account_metas.len() as u8 - 1] {
             // Similar to the test above where we try to make CPI write into account
             // Similar to the test above where we try to make CPI write into account
-            // data. This variant is for when direct mapping is enabled.
+            // data. This variant is for when stricter_abi_and_runtime_constraints is enabled.
             let account = AccountSharedData::new(42, 0, &invoke_program_id);
             let account = AccountSharedData::new(42, 0, &invoke_program_id);
             bank.store_account(&account_keypair.pubkey(), &account);
             bank.store_account(&account_keypair.pubkey(), &account);
             let account = AccountSharedData::new(42, 0, &invoke_program_id);
             let account = AccountSharedData::new(42, 0, &invoke_program_id);
@@ -3892,7 +3892,7 @@ fn test_cpi_account_ownership_writability() {
             let message = Message::new(&[instruction], Some(&mint_pubkey));
             let message = Message::new(&[instruction], Some(&mint_pubkey));
             let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
             let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
             let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
             let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
-            if direct_mapping {
+            if stricter_abi_and_runtime_constraints {
                 assert_eq!(
                 assert_eq!(
                     result.unwrap_err(),
                     result.unwrap_err(),
                     TransactionError::InstructionError(
                     TransactionError::InstructionError(
@@ -3934,7 +3934,7 @@ fn test_cpi_account_ownership_writability() {
 fn test_cpi_account_data_updates() {
 fn test_cpi_account_data_updates() {
     solana_logger::setup();
     solana_logger::setup();
 
 
-    for (deprecated_callee, deprecated_caller, direct_mapping) in
+    for (deprecated_callee, deprecated_caller, stricter_abi_and_runtime_constraints) in
         [false, true].into_iter().flat_map(move |z| {
         [false, true].into_iter().flat_map(move |z| {
             [false, true]
             [false, true]
                 .into_iter()
                 .into_iter()
@@ -3948,8 +3948,8 @@ fn test_cpi_account_data_updates() {
         } = create_genesis_config(100_123_456_789);
         } = create_genesis_config(100_123_456_789);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut feature_set = FeatureSet::all_enabled();
         let mut feature_set = FeatureSet::all_enabled();
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
 
 
         bank.feature_set = Arc::new(feature_set);
         bank.feature_set = Arc::new(feature_set);
@@ -4019,7 +4019,7 @@ fn test_cpi_account_data_updates() {
                 result.unwrap_err().unwrap(),
                 result.unwrap_err().unwrap(),
                 TransactionError::InstructionError(
                 TransactionError::InstructionError(
                     0,
                     0,
-                    if direct_mapping {
+                    if stricter_abi_and_runtime_constraints {
                         InstructionError::ProgramFailedToComplete
                         InstructionError::ProgramFailedToComplete
                     } else {
                     } else {
                         InstructionError::ModifiedProgramId
                         InstructionError::ModifiedProgramId
@@ -4058,7 +4058,7 @@ fn test_cpi_account_data_updates() {
                 result.unwrap_err().unwrap(),
                 result.unwrap_err().unwrap(),
                 TransactionError::InstructionError(
                 TransactionError::InstructionError(
                     0,
                     0,
-                    if direct_mapping {
+                    if stricter_abi_and_runtime_constraints {
                         InstructionError::InvalidRealloc
                         InstructionError::InvalidRealloc
                     } else {
                     } else {
                         InstructionError::AccountDataSizeChanged
                         InstructionError::AccountDataSizeChanged
@@ -4082,7 +4082,7 @@ fn test_cpi_account_data_updates() {
         bank.store_account(&account_keypair.pubkey(), &account);
         bank.store_account(&account_keypair.pubkey(), &account);
         let mut instruction_data = vec![
         let mut instruction_data = vec![
             TEST_CPI_ACCOUNT_UPDATE_CALLEE_SHRINKS_SMALLER_THAN_ORIGINAL_LEN,
             TEST_CPI_ACCOUNT_UPDATE_CALLEE_SHRINKS_SMALLER_THAN_ORIGINAL_LEN,
-            direct_mapping as u8,
+            stricter_abi_and_runtime_constraints as u8,
         ];
         ];
         instruction_data.extend_from_slice(4usize.to_le_bytes().as_ref());
         instruction_data.extend_from_slice(4usize.to_le_bytes().as_ref());
         let instruction = Instruction::new_with_bytes(
         let instruction = Instruction::new_with_bytes(
@@ -4101,7 +4101,7 @@ fn test_cpi_account_data_updates() {
                 result.unwrap_err().unwrap(),
                 result.unwrap_err().unwrap(),
                 TransactionError::InstructionError(
                 TransactionError::InstructionError(
                     0,
                     0,
-                    if direct_mapping && deprecated_callee {
+                    if stricter_abi_and_runtime_constraints && deprecated_callee {
                         InstructionError::InvalidRealloc
                         InstructionError::InvalidRealloc
                     } else {
                     } else {
                         InstructionError::AccountDataSizeChanged
                         InstructionError::AccountDataSizeChanged
@@ -4124,7 +4124,7 @@ fn test_cpi_account_data_updates() {
         bank.store_account(&account_keypair.pubkey(), &account);
         bank.store_account(&account_keypair.pubkey(), &account);
         let mut instruction_data = vec![
         let mut instruction_data = vec![
             TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS_CALLEE_SHRINKS,
             TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS_CALLEE_SHRINKS,
-            direct_mapping as u8,
+            stricter_abi_and_runtime_constraints as u8,
         ];
         ];
         // realloc to "foobazbad" then shrink to "foobazb"
         // realloc to "foobazbad" then shrink to "foobazb"
         instruction_data.extend_from_slice(7usize.to_le_bytes().as_ref());
         instruction_data.extend_from_slice(7usize.to_le_bytes().as_ref());
@@ -4140,7 +4140,7 @@ fn test_cpi_account_data_updates() {
                 result.unwrap_err().unwrap(),
                 result.unwrap_err().unwrap(),
                 TransactionError::InstructionError(
                 TransactionError::InstructionError(
                     0,
                     0,
-                    if direct_mapping {
+                    if stricter_abi_and_runtime_constraints {
                         InstructionError::ProgramFailedToComplete
                         InstructionError::ProgramFailedToComplete
                     } else {
                     } else {
                         InstructionError::ModifiedProgramId
                         InstructionError::ModifiedProgramId
@@ -4161,7 +4161,7 @@ fn test_cpi_account_data_updates() {
         bank.store_account(&account_keypair.pubkey(), &account);
         bank.store_account(&account_keypair.pubkey(), &account);
         let mut instruction_data = vec![
         let mut instruction_data = vec![
             TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS_CALLEE_SHRINKS,
             TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS_CALLEE_SHRINKS,
-            direct_mapping as u8,
+            stricter_abi_and_runtime_constraints as u8,
         ];
         ];
         // realloc to "foobazbad" then shrink to "f"
         // realloc to "foobazbad" then shrink to "f"
         instruction_data.extend_from_slice(1usize.to_le_bytes().as_ref());
         instruction_data.extend_from_slice(1usize.to_le_bytes().as_ref());
@@ -4177,7 +4177,7 @@ fn test_cpi_account_data_updates() {
                 result.unwrap_err().unwrap(),
                 result.unwrap_err().unwrap(),
                 TransactionError::InstructionError(
                 TransactionError::InstructionError(
                     0,
                     0,
-                    if direct_mapping {
+                    if stricter_abi_and_runtime_constraints {
                         InstructionError::ProgramFailedToComplete
                         InstructionError::ProgramFailedToComplete
                     } else {
                     } else {
                         InstructionError::ModifiedProgramId
                         InstructionError::ModifiedProgramId
@@ -4394,13 +4394,13 @@ fn test_deny_access_beyond_current_length() {
         ..
         ..
     } = create_genesis_config(100_123_456_789);
     } = create_genesis_config(100_123_456_789);
 
 
-    for direct_mapping in [false, true] {
+    for stricter_abi_and_runtime_constraints in [false, true] {
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         // by default test banks have all features enabled, so we only need to
         // by default test banks have all features enabled, so we only need to
         // disable when needed
         // disable when needed
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let mut bank_client = BankClient::new_shared(bank);
         let mut bank_client = BankClient::new_shared(bank);
@@ -4439,7 +4439,7 @@ fn test_deny_access_beyond_current_length() {
                 account_metas.clone(),
                 account_metas.clone(),
             );
             );
             let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
             let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
-            if direct_mapping {
+            if stricter_abi_and_runtime_constraints {
                 assert_eq!(
                 assert_eq!(
                     result.unwrap_err().unwrap(),
                     result.unwrap_err().unwrap(),
                     TransactionError::InstructionError(0, expected_error)
                     TransactionError::InstructionError(0, expected_error)
@@ -4462,13 +4462,13 @@ fn test_deny_executable_write() {
         ..
         ..
     } = create_genesis_config(100_123_456_789);
     } = create_genesis_config(100_123_456_789);
 
 
-    for direct_mapping in [false, true] {
+    for stricter_abi_and_runtime_constraints in [false, true] {
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         // by default test banks have all features enabled, so we only need to
         // by default test banks have all features enabled, so we only need to
         // disable when needed
         // disable when needed
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let mut bank_client = BankClient::new_shared(bank);
         let mut bank_client = BankClient::new_shared(bank);
@@ -4517,13 +4517,13 @@ fn test_update_callee_account() {
         ..
         ..
     } = create_genesis_config(100_123_456_789);
     } = create_genesis_config(100_123_456_789);
 
 
-    for direct_mapping in [false, true] {
+    for stricter_abi_and_runtime_constraints in [false, true] {
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         // by default test banks have all features enabled, so we only need to
         // by default test banks have all features enabled, so we only need to
         // disable when needed
         // disable when needed
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let mut bank_client = BankClient::new_shared(bank.clone());
         let mut bank_client = BankClient::new_shared(bank.clone());
@@ -4547,7 +4547,7 @@ fn test_update_callee_account() {
             AccountMeta::new_readonly(invoke_program_id, false),
             AccountMeta::new_readonly(invoke_program_id, false),
         ];
         ];
 
 
-        // I. do CPI with account in read only (separate code path with direct mapping)
+        // I. do CPI with account in read only (separate code path with stricter_abi_and_runtime_constraints)
         let mut account = AccountSharedData::new(42, 10240, &invoke_program_id);
         let mut account = AccountSharedData::new(42, 10240, &invoke_program_id);
         let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
         let data: Vec<u8> = (0..10240).map(|n| n as u8).collect();
         account.set_data(data);
         account.set_data(data);
@@ -4753,7 +4753,7 @@ fn test_update_callee_account() {
         );
         );
         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 
 
-        if direct_mapping {
+        if stricter_abi_and_runtime_constraints {
             // changing the data pointer is not permitted
             // changing the data pointer is not permitted
             assert!(result.is_err());
             assert!(result.is_err());
         } else {
         } else {
@@ -4801,13 +4801,13 @@ fn test_account_info_in_account() {
     }
     }
 
 
     for program in programs {
     for program in programs {
-        for direct_mapping in [false, true] {
+        for stricter_abi_and_runtime_constraints in [false, true] {
             let mut bank = Bank::new_for_tests(&genesis_config);
             let mut bank = Bank::new_for_tests(&genesis_config);
             let feature_set = Arc::make_mut(&mut bank.feature_set);
             let feature_set = Arc::make_mut(&mut bank.feature_set);
             // by default test banks have all features enabled, so we only need to
             // by default test banks have all features enabled, so we only need to
             // disable when needed
             // disable when needed
-            if !direct_mapping {
-                feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+            if !stricter_abi_and_runtime_constraints {
+                feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
             }
             }
 
 
             let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
             let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
@@ -4843,7 +4843,7 @@ fn test_account_info_in_account() {
             bank.store_account(&account_keypair.pubkey(), &account);
             bank.store_account(&account_keypair.pubkey(), &account);
 
 
             let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
             let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
-            if direct_mapping {
+            if stricter_abi_and_runtime_constraints {
                 assert!(result.is_err());
                 assert!(result.is_err());
             } else {
             } else {
                 assert!(result.is_ok());
                 assert!(result.is_ok());
@@ -4862,13 +4862,13 @@ fn test_account_info_rc_in_account() {
         ..
         ..
     } = create_genesis_config(100_123_456_789);
     } = create_genesis_config(100_123_456_789);
 
 
-    for direct_mapping in [false, true] {
+    for stricter_abi_and_runtime_constraints in [false, true] {
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         let feature_set = Arc::make_mut(&mut bank.feature_set);
         // by default test banks have all features enabled, so we only need to
         // by default test banks have all features enabled, so we only need to
         // disable when needed
         // disable when needed
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
 
 
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
@@ -4909,7 +4909,7 @@ fn test_account_info_rc_in_account() {
         let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
         let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
         let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
         let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
 
 
-        if direct_mapping {
+        if stricter_abi_and_runtime_constraints {
             assert!(
             assert!(
                 logs.last().unwrap().ends_with(" failed: Invalid pointer"),
                 logs.last().unwrap().ends_with(" failed: Invalid pointer"),
                 "{logs:?}"
                 "{logs:?}"
@@ -4932,7 +4932,7 @@ fn test_account_info_rc_in_account() {
         let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
         let tx = Transaction::new(&[&mint_keypair], message.clone(), bank.last_blockhash());
         let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
         let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
 
 
-        if direct_mapping {
+        if stricter_abi_and_runtime_constraints {
             assert!(
             assert!(
                 logs.last().unwrap().ends_with(" failed: Invalid pointer"),
                 logs.last().unwrap().ends_with(" failed: Invalid pointer"),
                 "{logs:?}"
                 "{logs:?}"
@@ -4958,7 +4958,7 @@ fn test_clone_account_data() {
     let mut bank = Bank::new_for_tests(&genesis_config);
     let mut bank = Bank::new_for_tests(&genesis_config);
     let feature_set = Arc::make_mut(&mut bank.feature_set);
     let feature_set = Arc::make_mut(&mut bank.feature_set);
 
 
-    feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+    feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
 
 
     let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
     let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
     let mut bank_client = BankClient::new_shared(bank.clone());
     let mut bank_client = BankClient::new_shared(bank.clone());
@@ -5291,7 +5291,7 @@ fn test_function_call_args() {
 fn test_mem_syscalls_overlap_account_begin_or_end() {
 fn test_mem_syscalls_overlap_account_begin_or_end() {
     solana_logger::setup();
     solana_logger::setup();
 
 
-    for direct_mapping in [false, true] {
+    for stricter_abi_and_runtime_constraints in [false, true] {
         let GenesisConfigInfo {
         let GenesisConfigInfo {
             genesis_config,
             genesis_config,
             mint_keypair,
             mint_keypair,
@@ -5300,8 +5300,8 @@ fn test_mem_syscalls_overlap_account_begin_or_end() {
 
 
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut feature_set = FeatureSet::all_enabled();
         let mut feature_set = FeatureSet::all_enabled();
-        if !direct_mapping {
-            feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
+        if !stricter_abi_and_runtime_constraints {
+            feature_set.deactivate(&feature_set::stricter_abi_and_runtime_constraints::id());
         }
         }
 
 
         let account_keypair = Keypair::new();
         let account_keypair = Keypair::new();
@@ -5344,7 +5344,7 @@ fn test_mem_syscalls_overlap_account_begin_or_end() {
             bank.store_account(&account_keypair.pubkey(), &account);
             bank.store_account(&account_keypair.pubkey(), &account);
 
 
             for instr in 0..=15 {
             for instr in 0..=15 {
-                println!("Testing deprecated:{deprecated} direct_mapping:{direct_mapping} instruction:{instr}");
+                println!("Testing deprecated:{deprecated} stricter_abi_and_runtime_constraints:{stricter_abi_and_runtime_constraints} instruction:{instr}");
                 let instruction =
                 let instruction =
                     Instruction::new_with_bytes(program_id, &[instr], account_metas.clone());
                     Instruction::new_with_bytes(program_id, &[instr], account_metas.clone());
 
 
@@ -5353,7 +5353,7 @@ fn test_mem_syscalls_overlap_account_begin_or_end() {
                 let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
                 let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
                 let last_line = logs.last().unwrap();
                 let last_line = logs.last().unwrap();
 
 
-                if direct_mapping {
+                if stricter_abi_and_runtime_constraints {
                     assert!(last_line.contains(" failed: Access violation"), "{logs:?}");
                     assert!(last_line.contains(" failed: Access violation"), "{logs:?}");
                 } else {
                 } else {
                     assert!(result.is_ok(), "{logs:?}");
                     assert!(result.is_ok(), "{logs:?}");
@@ -5364,7 +5364,7 @@ fn test_mem_syscalls_overlap_account_begin_or_end() {
             bank.store_account(&account_keypair.pubkey(), &account);
             bank.store_account(&account_keypair.pubkey(), &account);
 
 
             for instr in 0..=15 {
             for instr in 0..=15 {
-                println!("Testing deprecated:{deprecated} direct_mapping:{direct_mapping} instruction:{instr} zero-length account");
+                println!("Testing deprecated:{deprecated} stricter_abi_and_runtime_constraints:{stricter_abi_and_runtime_constraints} instruction:{instr} zero-length account");
                 let instruction =
                 let instruction =
                     Instruction::new_with_bytes(program_id, &[instr, 0], account_metas.clone());
                     Instruction::new_with_bytes(program_id, &[instr, 0], account_metas.clone());
 
 
@@ -5373,7 +5373,7 @@ fn test_mem_syscalls_overlap_account_begin_or_end() {
                 let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
                 let (result, _, logs, _) = process_transaction_and_record_inner(&bank, tx);
                 let last_line = logs.last().unwrap();
                 let last_line = logs.last().unwrap();
 
 
-                if direct_mapping && (!deprecated || instr < 8) {
+                if stricter_abi_and_runtime_constraints && (!deprecated || instr < 8) {
                     assert!(
                     assert!(
                         last_line.contains(" failed: account data too small")
                         last_line.contains(" failed: account data too small")
                             || last_line.contains(" failed: Failed to reallocate account data")
                             || last_line.contains(" failed: Failed to reallocate account data")
@@ -5381,7 +5381,7 @@ fn test_mem_syscalls_overlap_account_begin_or_end() {
                         "{logs:?}",
                         "{logs:?}",
                     );
                     );
                 } else {
                 } else {
-                    // direct_mapping && deprecated && instr >= 8 succeeds with zero-length accounts
+                    // stricter_abi_and_runtime_constraints && deprecated && instr >= 8 succeeds with zero-length accounts
                     // because there is no MemoryRegion for the account,
                     // because there is no MemoryRegion for the account,
                     // so there can be no error when leaving that non-existent region.
                     // so there can be no error when leaving that non-existent region.
                     assert!(result.is_ok(), "{logs:?}");
                     assert!(result.is_ok(), "{logs:?}");

+ 2 - 2
svm-feature-set/src/lib.rs

@@ -2,7 +2,7 @@
 pub struct SVMFeatureSet {
 pub struct SVMFeatureSet {
     pub move_precompile_verification_to_svm: bool,
     pub move_precompile_verification_to_svm: bool,
     pub remove_accounts_executable_flag_checks: bool,
     pub remove_accounts_executable_flag_checks: bool,
-    pub bpf_account_data_direct_mapping: bool,
+    pub stricter_abi_and_runtime_constraints: bool,
     pub enable_bpf_loader_set_authority_checked_ix: bool,
     pub enable_bpf_loader_set_authority_checked_ix: bool,
     pub enable_loader_v4: bool,
     pub enable_loader_v4: bool,
     pub deplete_cu_meter_on_vm_failure: bool,
     pub deplete_cu_meter_on_vm_failure: bool,
@@ -45,7 +45,7 @@ impl SVMFeatureSet {
         Self {
         Self {
             move_precompile_verification_to_svm: true,
             move_precompile_verification_to_svm: true,
             remove_accounts_executable_flag_checks: true,
             remove_accounts_executable_flag_checks: true,
-            bpf_account_data_direct_mapping: true,
+            stricter_abi_and_runtime_constraints: true,
             enable_bpf_loader_set_authority_checked_ix: true,
             enable_bpf_loader_set_authority_checked_ix: true,
             enable_loader_v4: true,
             enable_loader_v4: true,
             deplete_cu_meter_on_vm_failure: true,
             deplete_cu_meter_on_vm_failure: true,

+ 2 - 17
svm/tests/integration_test.rs

@@ -24,7 +24,7 @@ use {
     solana_nonce::{self as nonce, state::DurableNonce},
     solana_nonce::{self as nonce, state::DurableNonce},
     solana_program_entrypoint::MAX_PERMITTED_DATA_INCREASE,
     solana_program_entrypoint::MAX_PERMITTED_DATA_INCREASE,
     solana_program_runtime::execution_budget::SVMTransactionExecutionAndFeeBudgetLimits,
     solana_program_runtime::execution_budget::SVMTransactionExecutionAndFeeBudgetLimits,
-    solana_pubkey::{pubkey, Pubkey},
+    solana_pubkey::Pubkey,
     solana_sdk_ids::{bpf_loader_upgradeable, native_loader},
     solana_sdk_ids::{bpf_loader_upgradeable, native_loader},
     solana_signer::Signer,
     solana_signer::Signer,
     solana_svm::{
     solana_svm::{
@@ -296,7 +296,7 @@ impl SvmTestEnvironment<'_> {
 }
 }
 
 
 // container for a transaction batch and all data needed to run and verify it against svm
 // container for a transaction batch and all data needed to run and verify it against svm
-#[derive(Clone, Debug)]
+#[derive(Clone, Default, Debug)]
 pub struct SvmTestEntry {
 pub struct SvmTestEntry {
     // features are enabled by default; these will be disabled
     // features are enabled by default; these will be disabled
     pub disabled_features: Vec<Pubkey>,
     pub disabled_features: Vec<Pubkey>,
@@ -497,21 +497,6 @@ impl SvmTestEntry {
     }
     }
 }
 }
 
 
-// NOTE `1ncomp1ete111111111111111111111111111111111` corresponds to `bpf_account_data_direct_mapping::id()`
-// by hardcoding the string, we ensure when the feature is finished, it will automatically be tested
-impl Default for SvmTestEntry {
-    fn default() -> Self {
-        Self {
-            disabled_features: vec![pubkey!("1ncomp1ete111111111111111111111111111111111")],
-            with_loader_v4: false,
-            initial_programs: vec![],
-            initial_accounts: AccountsMap::default(),
-            transaction_batch: vec![],
-            final_accounts: AccountsMap::default(),
-        }
-    }
-}
-
 // one transaction in a batch plus check results for svm and asserts for tests
 // one transaction in a batch plus check results for svm and asserts for tests
 #[derive(Clone, Debug)]
 #[derive(Clone, Debug)]
 pub struct TransactionBatchItem {
 pub struct TransactionBatchItem {

+ 189 - 111
syscalls/src/cpi.rs

@@ -5,7 +5,8 @@ use {
     solana_loader_v3_interface::instruction as bpf_loader_upgradeable,
     solana_loader_v3_interface::instruction as bpf_loader_upgradeable,
     solana_measure::measure::Measure,
     solana_measure::measure::Measure,
     solana_program_runtime::{
     solana_program_runtime::{
-        invoke_context::SerializedAccountMetadata, serialization::create_memory_region_of_account,
+        invoke_context::SerializedAccountMetadata,
+        serialization::{create_memory_region_of_account, modify_memory_region_of_account},
     },
     },
     solana_sbpf::ebpf,
     solana_sbpf::ebpf,
     solana_stable_layout::stable_instruction::StableInstruction,
     solana_stable_layout::stable_instruction::StableInstruction,
@@ -77,8 +78,7 @@ struct CallerAccount<'a> {
     // mapped inside the vm (see serialize_parameters() in
     // mapped inside the vm (see serialize_parameters() in
     // BpfExecutor::execute).
     // BpfExecutor::execute).
     //
     //
-    // This is only set when direct mapping is off (see the relevant comment in
-    // CallerAccount::from_account_info).
+    // This is only set when account_data_direct_mapping is off.
     serialized_data: &'a mut [u8],
     serialized_data: &'a mut [u8],
     // Given the corresponding input AccountInfo::data, vm_data_addr points to
     // Given the corresponding input AccountInfo::data, vm_data_addr points to
     // the pointer field and ref_to_len_in_vm points to the length field.
     // the pointer field and ref_to_len_in_vm points to the length field.
@@ -87,6 +87,41 @@ struct CallerAccount<'a> {
 }
 }
 
 
 impl<'a> CallerAccount<'a> {
 impl<'a> CallerAccount<'a> {
+    fn get_serialized_data(
+        memory_mapping: &MemoryMapping<'_>,
+        vm_addr: u64,
+        len: u64,
+        stricter_abi_and_runtime_constraints: bool,
+        account_data_direct_mapping: bool,
+    ) -> Result<&'a mut [u8], Error> {
+        if stricter_abi_and_runtime_constraints && account_data_direct_mapping {
+            Ok(&mut [])
+        } else if stricter_abi_and_runtime_constraints {
+            // Workaround the memory permissions (as these are from the PoV of being inside the VM)
+            let serialization_ptr = translate_slice_mut::<u8>(
+                memory_mapping,
+                solana_sbpf::ebpf::MM_INPUT_START,
+                1,
+                false, // Don't care since it is byte aligned
+            )?
+            .as_mut_ptr();
+            unsafe {
+                Ok(std::slice::from_raw_parts_mut(
+                    serialization_ptr
+                        .add(vm_addr.saturating_sub(solana_sbpf::ebpf::MM_INPUT_START) as usize),
+                    len as usize,
+                ))
+            }
+        } else {
+            translate_slice_mut::<u8>(
+                memory_mapping,
+                vm_addr,
+                len,
+                false, // Don't care since it is byte aligned
+            )
+        }
+    }
+
     // Create a CallerAccount given an AccountInfo.
     // Create a CallerAccount given an AccountInfo.
     fn from_account_info(
     fn from_account_info(
         invoke_context: &InvokeContext,
         invoke_context: &InvokeContext,
@@ -96,11 +131,11 @@ impl<'a> CallerAccount<'a> {
         account_info: &AccountInfo,
         account_info: &AccountInfo,
         account_metadata: &SerializedAccountMetadata,
         account_metadata: &SerializedAccountMetadata,
     ) -> Result<CallerAccount<'a>, Error> {
     ) -> Result<CallerAccount<'a>, Error> {
-        let direct_mapping = invoke_context
+        let stricter_abi_and_runtime_constraints = invoke_context
             .get_feature_set()
             .get_feature_set()
-            .bpf_account_data_direct_mapping;
+            .stricter_abi_and_runtime_constraints;
 
 
-        if direct_mapping {
+        if stricter_abi_and_runtime_constraints {
             check_account_info_pointer(
             check_account_info_pointer(
                 invoke_context,
                 invoke_context,
                 account_info.key as *const _ as u64,
                 account_info.key as *const _ as u64,
@@ -124,7 +159,7 @@ impl<'a> CallerAccount<'a> {
                 account_info.lamports.as_ptr() as u64,
                 account_info.lamports.as_ptr() as u64,
                 check_aligned,
                 check_aligned,
             )?;
             )?;
-            if direct_mapping {
+            if stricter_abi_and_runtime_constraints {
                 if account_info.lamports.as_ptr() as u64 >= ebpf::MM_INPUT_START {
                 if account_info.lamports.as_ptr() as u64 >= ebpf::MM_INPUT_START {
                     return Err(SyscallError::InvalidPointer.into());
                     return Err(SyscallError::InvalidPointer.into());
                 }
                 }
@@ -146,7 +181,9 @@ impl<'a> CallerAccount<'a> {
         )?;
         )?;
 
 
         let (serialized_data, vm_data_addr, ref_to_len_in_vm) = {
         let (serialized_data, vm_data_addr, ref_to_len_in_vm) = {
-            if direct_mapping && account_info.data.as_ptr() as u64 >= ebpf::MM_INPUT_START {
+            if stricter_abi_and_runtime_constraints
+                && account_info.data.as_ptr() as u64 >= ebpf::MM_INPUT_START
+            {
                 return Err(SyscallError::InvalidPointer.into());
                 return Err(SyscallError::InvalidPointer.into());
             }
             }
 
 
@@ -156,7 +193,7 @@ impl<'a> CallerAccount<'a> {
                 account_info.data.as_ptr() as *const _ as u64,
                 account_info.data.as_ptr() as *const _ as u64,
                 check_aligned,
                 check_aligned,
             )?;
             )?;
-            if direct_mapping {
+            if stricter_abi_and_runtime_constraints {
                 check_account_info_pointer(
                 check_account_info_pointer(
                     invoke_context,
                     invoke_context,
                     data.as_ptr() as u64,
                     data.as_ptr() as u64,
@@ -174,7 +211,7 @@ impl<'a> CallerAccount<'a> {
 
 
             let vm_len_addr = (account_info.data.as_ptr() as *const u64 as u64)
             let vm_len_addr = (account_info.data.as_ptr() as *const u64 as u64)
                 .saturating_add(size_of::<u64>() as u64);
                 .saturating_add(size_of::<u64>() as u64);
-            if direct_mapping {
+            if stricter_abi_and_runtime_constraints {
                 // In the same vein as the other check_account_info_pointer() checks, we don't lock
                 // In the same vein as the other check_account_info_pointer() checks, we don't lock
                 // this pointer to a specific address but we don't want it to be inside accounts, or
                 // this pointer to a specific address but we don't want it to be inside accounts, or
                 // callees might be able to write to the pointed memory.
                 // callees might be able to write to the pointed memory.
@@ -184,29 +221,13 @@ impl<'a> CallerAccount<'a> {
             }
             }
             let ref_to_len_in_vm = translate_type_mut::<u64>(memory_mapping, vm_len_addr, false)?;
             let ref_to_len_in_vm = translate_type_mut::<u64>(memory_mapping, vm_len_addr, false)?;
             let vm_data_addr = data.as_ptr() as u64;
             let vm_data_addr = data.as_ptr() as u64;
-
-            let serialized_data = if direct_mapping {
-                // when direct mapping is enabled, the permissions on the
-                // realloc region can change during CPI so we must delay
-                // translating until when we know whether we're going to mutate
-                // the realloc region or not. Consider this case:
-                //
-                // [caller can't write to an account] <- we are here
-                // [callee grows and assigns account to the caller]
-                // [caller can now write to the account]
-                //
-                // If we always translated the realloc area here, we'd get a
-                // memory access violation since we can't write to the account
-                // _yet_, but we will be able to once the caller returns.
-                &mut []
-            } else {
-                translate_slice_mut::<u8>(
-                    memory_mapping,
-                    vm_data_addr,
-                    data.len() as u64,
-                    check_aligned,
-                )?
-            };
+            let serialized_data = CallerAccount::get_serialized_data(
+                memory_mapping,
+                vm_data_addr,
+                data.len() as u64,
+                stricter_abi_and_runtime_constraints,
+                invoke_context.account_data_direct_mapping,
+            )?;
             (serialized_data, vm_data_addr, ref_to_len_in_vm)
             (serialized_data, vm_data_addr, ref_to_len_in_vm)
         };
         };
 
 
@@ -229,11 +250,11 @@ impl<'a> CallerAccount<'a> {
         account_info: &SolAccountInfo,
         account_info: &SolAccountInfo,
         account_metadata: &SerializedAccountMetadata,
         account_metadata: &SerializedAccountMetadata,
     ) -> Result<CallerAccount<'a>, Error> {
     ) -> Result<CallerAccount<'a>, Error> {
-        let direct_mapping = invoke_context
+        let stricter_abi_and_runtime_constraints = invoke_context
             .get_feature_set()
             .get_feature_set()
-            .bpf_account_data_direct_mapping;
+            .stricter_abi_and_runtime_constraints;
 
 
-        if direct_mapping {
+        if stricter_abi_and_runtime_constraints {
             check_account_info_pointer(
             check_account_info_pointer(
                 invoke_context,
                 invoke_context,
                 account_info.key_addr,
                 account_info.key_addr,
@@ -278,17 +299,13 @@ impl<'a> CallerAccount<'a> {
                 .unwrap_or(u64::MAX),
                 .unwrap_or(u64::MAX),
         )?;
         )?;
 
 
-        let serialized_data = if direct_mapping {
-            // See comment in CallerAccount::from_account_info()
-            &mut []
-        } else {
-            translate_slice_mut::<u8>(
-                memory_mapping,
-                account_info.data_addr,
-                account_info.data_len,
-                check_aligned,
-            )?
-        };
+        let serialized_data = CallerAccount::get_serialized_data(
+            memory_mapping,
+            account_info.data_addr,
+            account_info.data_len,
+            stricter_abi_and_runtime_constraints,
+            invoke_context.account_data_direct_mapping,
+        )?;
 
 
         // we already have the host addr we want: &mut account_info.data_len.
         // we already have the host addr we want: &mut account_info.data_len.
         // The account info might be read only in the vm though, so we translate
         // The account info might be read only in the vm though, so we translate
@@ -715,14 +732,14 @@ fn translate_account_infos<'a, T, F>(
 where
 where
     F: Fn(&T) -> u64,
     F: Fn(&T) -> u64,
 {
 {
-    let direct_mapping = invoke_context
+    let stricter_abi_and_runtime_constraints = invoke_context
         .get_feature_set()
         .get_feature_set()
-        .bpf_account_data_direct_mapping;
+        .stricter_abi_and_runtime_constraints;
 
 
     // In the same vein as the other check_account_info_pointer() checks, we don't lock
     // In the same vein as the other check_account_info_pointer() checks, we don't lock
     // this pointer to a specific address but we don't want it to be inside accounts, or
     // this pointer to a specific address but we don't want it to be inside accounts, or
     // callees might be able to write to the pointed memory.
     // callees might be able to write to the pointed memory.
-    if direct_mapping
+    if stricter_abi_and_runtime_constraints
         && account_infos_addr
         && account_infos_addr
             .saturating_add(account_infos_len.saturating_mul(std::mem::size_of::<T>() as u64))
             .saturating_add(account_infos_len.saturating_mul(std::mem::size_of::<T>() as u64))
             >= ebpf::MM_INPUT_START
             >= ebpf::MM_INPUT_START
@@ -786,9 +803,9 @@ where
         .unwrap()
         .unwrap()
         .accounts_metadata;
         .accounts_metadata;
 
 
-    let direct_mapping = invoke_context
+    let stricter_abi_and_runtime_constraints = invoke_context
         .get_feature_set()
         .get_feature_set()
-        .bpf_account_data_direct_mapping;
+        .stricter_abi_and_runtime_constraints;
 
 
     for (instruction_account_index, instruction_account) in
     for (instruction_account_index, instruction_account) in
         next_instruction_accounts.iter().enumerate()
         next_instruction_accounts.iter().enumerate()
@@ -851,10 +868,11 @@ where
             // BorrowedAccount (callee_account) so the callee can see the
             // BorrowedAccount (callee_account) so the callee can see the
             // changes.
             // changes.
             let update_caller = update_callee_account(
             let update_caller = update_callee_account(
+                check_aligned,
                 &caller_account,
                 &caller_account,
                 callee_account,
                 callee_account,
-                direct_mapping,
-                check_aligned,
+                stricter_abi_and_runtime_constraints,
+                invoke_context.account_data_direct_mapping,
             )?;
             )?;
 
 
             accounts.push(TranslatedAccount {
             accounts.push(TranslatedAccount {
@@ -1039,9 +1057,9 @@ fn cpi_common<S: SyscallInvokeSigned>(
     // CPI exit.
     // CPI exit.
     //
     //
     // Synchronize the callee's account changes so the caller can see them.
     // Synchronize the callee's account changes so the caller can see them.
-    let direct_mapping = invoke_context
+    let stricter_abi_and_runtime_constraints = invoke_context
         .get_feature_set()
         .get_feature_set()
-        .bpf_account_data_direct_mapping;
+        .stricter_abi_and_runtime_constraints;
 
 
     for translate_account in accounts.iter_mut() {
     for translate_account in accounts.iter_mut() {
         let mut callee_account = instruction_context.try_borrow_instruction_account(
         let mut callee_account = instruction_context.try_borrow_instruction_account(
@@ -1055,12 +1073,12 @@ fn cpi_common<S: SyscallInvokeSigned>(
                 check_aligned,
                 check_aligned,
                 &mut translate_account.caller_account,
                 &mut translate_account.caller_account,
                 &mut callee_account,
                 &mut callee_account,
-                direct_mapping,
+                stricter_abi_and_runtime_constraints,
             )?;
             )?;
         }
         }
     }
     }
 
 
-    if direct_mapping {
+    if stricter_abi_and_runtime_constraints {
         for translate_account in accounts.iter() {
         for translate_account in accounts.iter() {
             let mut callee_account = instruction_context.try_borrow_instruction_account(
             let mut callee_account = instruction_context.try_borrow_instruction_account(
                 transaction_context,
                 transaction_context,
@@ -1072,6 +1090,7 @@ fn cpi_common<S: SyscallInvokeSigned>(
                     check_aligned,
                     check_aligned,
                     &translate_account.caller_account,
                     &translate_account.caller_account,
                     &mut callee_account,
                     &mut callee_account,
+                    invoke_context.account_data_direct_mapping,
                 )?;
                 )?;
             }
             }
         }
         }
@@ -1091,12 +1110,13 @@ fn cpi_common<S: SyscallInvokeSigned>(
 // changes.
 // changes.
 //
 //
 // When true is returned, the caller account must be updated after CPI. This
 // When true is returned, the caller account must be updated after CPI. This
-// is only set for direct mapping when the pointer may have changed.
+// is only set for stricter_abi_and_runtime_constraints when the pointer may have changed.
 fn update_callee_account(
 fn update_callee_account(
+    check_aligned: bool,
     caller_account: &CallerAccount,
     caller_account: &CallerAccount,
     mut callee_account: BorrowedAccount<'_>,
     mut callee_account: BorrowedAccount<'_>,
-    direct_mapping: bool,
-    check_aligned: bool,
+    stricter_abi_and_runtime_constraints: bool,
+    account_data_direct_mapping: bool,
 ) -> Result<bool, Error> {
 ) -> Result<bool, Error> {
     let mut must_update_caller = false;
     let mut must_update_caller = false;
 
 
@@ -1104,7 +1124,7 @@ fn update_callee_account(
         callee_account.set_lamports(*caller_account.lamports)?;
         callee_account.set_lamports(*caller_account.lamports)?;
     }
     }
 
 
-    if direct_mapping {
+    if stricter_abi_and_runtime_constraints {
         let prev_len = callee_account.get_data().len();
         let prev_len = callee_account.get_data().len();
         let post_len = *caller_account.ref_to_len_in_vm as usize;
         let post_len = *caller_account.ref_to_len_in_vm as usize;
         if prev_len != post_len {
         if prev_len != post_len {
@@ -1123,6 +1143,9 @@ fn update_callee_account(
             // pointer to data may have changed, so caller must be updated
             // pointer to data may have changed, so caller must be updated
             must_update_caller = true;
             must_update_caller = true;
         }
         }
+        if !account_data_direct_mapping && callee_account.can_data_be_changed().is_ok() {
+            callee_account.set_data_from_slice(caller_account.serialized_data)?;
+        }
     } else {
     } else {
         // The redundant check helps to avoid the expensive data comparison if we can
         // The redundant check helps to avoid the expensive data comparison if we can
         match callee_account.can_data_be_resized(caller_account.serialized_data.len()) {
         match callee_account.can_data_be_resized(caller_account.serialized_data.len()) {
@@ -1149,6 +1172,7 @@ fn update_caller_account_region(
     check_aligned: bool,
     check_aligned: bool,
     caller_account: &CallerAccount,
     caller_account: &CallerAccount,
     callee_account: &mut BorrowedAccount<'_>,
     callee_account: &mut BorrowedAccount<'_>,
+    account_data_direct_mapping: bool,
 ) -> Result<(), Error> {
 ) -> Result<(), Error> {
     let is_caller_loader_deprecated = !check_aligned;
     let is_caller_loader_deprecated = !check_aligned;
     let address_space_reserved_for_account = if is_caller_loader_deprecated {
     let address_space_reserved_for_account = if is_caller_loader_deprecated {
@@ -1167,7 +1191,13 @@ fn update_caller_account_region(
             .ok_or_else(|| Box::new(InstructionError::MissingAccount))?;
             .ok_or_else(|| Box::new(InstructionError::MissingAccount))?;
         // vm_data_addr must always point to the beginning of the region
         // vm_data_addr must always point to the beginning of the region
         debug_assert_eq!(region.vm_addr, caller_account.vm_data_addr);
         debug_assert_eq!(region.vm_addr, caller_account.vm_data_addr);
-        let new_region = create_memory_region_of_account(callee_account, region.vm_addr)?;
+        let mut new_region;
+        if !account_data_direct_mapping {
+            new_region = region.clone();
+            modify_memory_region_of_account(callee_account, &mut new_region);
+        } else {
+            new_region = create_memory_region_of_account(callee_account, region.vm_addr)?;
+        }
         memory_mapping.replace_region(region_index, new_region)?;
         memory_mapping.replace_region(region_index, new_region)?;
     }
     }
 
 
@@ -1183,7 +1213,7 @@ fn update_caller_account_region(
 // This method updates caller_account so the CPI caller can see the callee's
 // This method updates caller_account so the CPI caller can see the callee's
 // changes.
 // changes.
 //
 //
-// Safety: Once `direct_mapping` is enabled all fields of [CallerAccount] used
+// Safety: Once `stricter_abi_and_runtime_constraints` is enabled all fields of [CallerAccount] used
 // in this function should never point inside the address space reserved for
 // in this function should never point inside the address space reserved for
 // accounts (regardless of the current size of an account).
 // accounts (regardless of the current size of an account).
 fn update_caller_account(
 fn update_caller_account(
@@ -1192,7 +1222,7 @@ fn update_caller_account(
     check_aligned: bool,
     check_aligned: bool,
     caller_account: &mut CallerAccount<'_>,
     caller_account: &mut CallerAccount<'_>,
     callee_account: &mut BorrowedAccount<'_>,
     callee_account: &mut BorrowedAccount<'_>,
-    direct_mapping: bool,
+    stricter_abi_and_runtime_constraints: bool,
 ) -> Result<(), Error> {
 ) -> Result<(), Error> {
     *caller_account.lamports = callee_account.get_lamports();
     *caller_account.lamports = callee_account.get_lamports();
     *caller_account.owner = *callee_account.get_owner();
     *caller_account.owner = *callee_account.get_owner();
@@ -1200,15 +1230,18 @@ fn update_caller_account(
     let prev_len = *caller_account.ref_to_len_in_vm as usize;
     let prev_len = *caller_account.ref_to_len_in_vm as usize;
     let post_len = callee_account.get_data().len();
     let post_len = callee_account.get_data().len();
     let is_caller_loader_deprecated = !check_aligned;
     let is_caller_loader_deprecated = !check_aligned;
-    let address_space_reserved_for_account = if direct_mapping && is_caller_loader_deprecated {
-        caller_account.original_data_len
-    } else {
-        caller_account
-            .original_data_len
-            .saturating_add(MAX_PERMITTED_DATA_INCREASE)
-    };
+    let address_space_reserved_for_account =
+        if stricter_abi_and_runtime_constraints && is_caller_loader_deprecated {
+            caller_account.original_data_len
+        } else {
+            caller_account
+                .original_data_len
+                .saturating_add(MAX_PERMITTED_DATA_INCREASE)
+        };
 
 
-    if post_len > address_space_reserved_for_account && (direct_mapping || prev_len != post_len) {
+    if post_len > address_space_reserved_for_account
+        && (stricter_abi_and_runtime_constraints || prev_len != post_len)
+    {
         let max_increase =
         let max_increase =
             address_space_reserved_for_account.saturating_sub(caller_account.original_data_len);
             address_space_reserved_for_account.saturating_sub(caller_account.original_data_len);
         ic_msg!(
         ic_msg!(
@@ -1219,9 +1252,9 @@ fn update_caller_account(
     }
     }
 
 
     if prev_len != post_len {
     if prev_len != post_len {
-        // when direct mapping is enabled we don't cache the serialized data in
+        // when stricter_abi_and_runtime_constraints is enabled we don't cache the serialized data in
         // caller_account.serialized_data. See CallerAccount::from_account_info.
         // caller_account.serialized_data. See CallerAccount::from_account_info.
-        if !direct_mapping {
+        if !(stricter_abi_and_runtime_constraints && invoke_context.account_data_direct_mapping) {
             // If the account has been shrunk, we're going to zero the unused memory
             // If the account has been shrunk, we're going to zero the unused memory
             // *that was previously used*.
             // *that was previously used*.
             if post_len < prev_len {
             if post_len < prev_len {
@@ -1232,11 +1265,12 @@ fn update_caller_account(
                     .fill(0);
                     .fill(0);
             }
             }
             // Set the length of caller_account.serialized_data to post_len.
             // Set the length of caller_account.serialized_data to post_len.
-            caller_account.serialized_data = translate_slice_mut::<u8>(
+            caller_account.serialized_data = CallerAccount::get_serialized_data(
                 memory_mapping,
                 memory_mapping,
                 caller_account.vm_data_addr,
                 caller_account.vm_data_addr,
                 post_len as u64,
                 post_len as u64,
-                false, // Don't care since it is byte aligned
+                stricter_abi_and_runtime_constraints,
+                invoke_context.account_data_direct_mapping,
             )?;
             )?;
         }
         }
         // this is the len field in the AccountInfo::data slice
         // this is the len field in the AccountInfo::data slice
@@ -1253,7 +1287,7 @@ fn update_caller_account(
         *serialized_len_ptr = post_len as u64;
         *serialized_len_ptr = post_len as u64;
     }
     }
 
 
-    if !direct_mapping {
+    if !(stricter_abi_and_runtime_constraints && invoke_context.account_data_direct_mapping) {
         // Propagate changes in the callee up to the caller.
         // Propagate changes in the callee up to the caller.
         let to_slice = &mut caller_account.serialized_data;
         let to_slice = &mut caller_account.serialized_data;
         let from_slice = callee_account
         let from_slice = callee_account
@@ -1322,7 +1356,7 @@ mod tests {
                 .map(|a| (a.0, a.1))
                 .map(|a| (a.0, a.1))
                 .collect::<Vec<TransactionAccount>>();
                 .collect::<Vec<TransactionAccount>>();
             let mut feature_set = SVMFeatureSet::all_enabled();
             let mut feature_set = SVMFeatureSet::all_enabled();
-            feature_set.bpf_account_data_direct_mapping = false;
+            feature_set.stricter_abi_and_runtime_constraints = false;
             let feature_set = &feature_set;
             let feature_set = &feature_set;
             with_mock_invoke_context_with_feature_set!(
             with_mock_invoke_context_with_feature_set!(
                 $invoke_context,
                 $invoke_context,
@@ -1480,7 +1514,7 @@ mod tests {
     }
     }
 
 
     #[test_matrix([false, true])]
     #[test_matrix([false, true])]
-    fn test_update_caller_account_lamports_owner(direct_mapping: bool) {
+    fn test_update_caller_account_lamports_owner(stricter_abi_and_runtime_constraints: bool) {
         let transaction_accounts = transaction_with_one_writable_instruction_account(vec![]);
         let transaction_accounts = transaction_with_one_writable_instruction_account(vec![]);
         let account = transaction_accounts[1].1.clone();
         let account = transaction_accounts[1].1.clone();
         mock_invoke_context!(
         mock_invoke_context!(
@@ -1521,7 +1555,7 @@ mod tests {
             true, // check_aligned
             true, // check_aligned
             &mut caller_account,
             &mut caller_account,
             &mut callee_account,
             &mut callee_account,
-            direct_mapping,
+            stricter_abi_and_runtime_constraints,
         )
         )
         .unwrap();
         .unwrap();
 
 
@@ -1650,7 +1684,7 @@ mod tests {
     }
     }
 
 
     #[test_matrix([false, true])]
     #[test_matrix([false, true])]
-    fn test_update_callee_account_lamports_owner(direct_mapping: bool) {
+    fn test_update_callee_account_lamports_owner(stricter_abi_and_runtime_constraints: bool) {
         let transaction_accounts = transaction_with_one_writable_instruction_account(vec![]);
         let transaction_accounts = transaction_with_one_writable_instruction_account(vec![]);
         let account = transaction_accounts[1].1.clone();
         let account = transaction_accounts[1].1.clone();
 
 
@@ -1673,7 +1707,14 @@ mod tests {
         *caller_account.lamports = 42;
         *caller_account.lamports = 42;
         *caller_account.owner = Pubkey::new_unique();
         *caller_account.owner = Pubkey::new_unique();
 
 
-        update_callee_account(&caller_account, callee_account, direct_mapping, true).unwrap();
+        update_callee_account(
+            true, // check_aligned
+            &caller_account,
+            callee_account,
+            stricter_abi_and_runtime_constraints,
+            true, // account_data_direct_mapping
+        )
+        .unwrap();
 
 
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         assert_eq!(callee_account.get_lamports(), 42);
         assert_eq!(callee_account.get_lamports(), 42);
@@ -1681,7 +1722,7 @@ mod tests {
     }
     }
 
 
     #[test_matrix([false, true])]
     #[test_matrix([false, true])]
-    fn test_update_callee_account_data_writable(direct_mapping: bool) {
+    fn test_update_callee_account_data_writable(stricter_abi_and_runtime_constraints: bool) {
         let transaction_accounts =
         let transaction_accounts =
             transaction_with_one_writable_instruction_account(b"foobar".to_vec());
             transaction_with_one_writable_instruction_account(b"foobar".to_vec());
         let account = transaction_accounts[1].1.clone();
         let account = transaction_accounts[1].1.clone();
@@ -1701,9 +1742,16 @@ mod tests {
         let mut caller_account = mock_caller_account.caller_account();
         let mut caller_account = mock_caller_account.caller_account();
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
 
 
-        // direct mapping does not copy data in update_callee_account()
+        // stricter_abi_and_runtime_constraints does not copy data in update_callee_account()
         caller_account.serialized_data[0] = b'b';
         caller_account.serialized_data[0] = b'b';
-        update_callee_account(&caller_account, callee_account, false, true).unwrap();
+        update_callee_account(
+            true, // check_aligned
+            &caller_account,
+            callee_account,
+            false, // stricter_abi_and_runtime_constraints
+            false, // account_data_direct_mapping
+        )
+        .unwrap();
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         assert_eq!(callee_account.get_data(), b"boobar");
         assert_eq!(callee_account.get_data(), b"boobar");
 
 
@@ -1712,8 +1760,15 @@ mod tests {
         *caller_account.ref_to_len_in_vm = data.len() as u64;
         *caller_account.ref_to_len_in_vm = data.len() as u64;
         caller_account.serialized_data = &mut data;
         caller_account.serialized_data = &mut data;
         assert_eq!(
         assert_eq!(
-            update_callee_account(&caller_account, callee_account, direct_mapping, true).unwrap(),
-            direct_mapping,
+            update_callee_account(
+                true, // check_aligned
+                &caller_account,
+                callee_account,
+                stricter_abi_and_runtime_constraints,
+                true, // account_data_direct_mapping
+            )
+            .unwrap(),
+            stricter_abi_and_runtime_constraints,
         );
         );
 
 
         // truncating resize
         // truncating resize
@@ -1722,8 +1777,15 @@ mod tests {
         caller_account.serialized_data = &mut data;
         caller_account.serialized_data = &mut data;
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         assert_eq!(
         assert_eq!(
-            update_callee_account(&caller_account, callee_account, direct_mapping, true).unwrap(),
-            direct_mapping,
+            update_callee_account(
+                true, // check_aligned
+                &caller_account,
+                callee_account,
+                stricter_abi_and_runtime_constraints,
+                true, // account_data_direct_mapping
+            )
+            .unwrap(),
+            stricter_abi_and_runtime_constraints,
         );
         );
 
 
         // close the account
         // close the account
@@ -1733,14 +1795,27 @@ mod tests {
         let mut owner = system_program::id();
         let mut owner = system_program::id();
         caller_account.owner = &mut owner;
         caller_account.owner = &mut owner;
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
-        update_callee_account(&caller_account, callee_account, direct_mapping, true).unwrap();
+        update_callee_account(
+            true, // check_aligned
+            &caller_account,
+            callee_account,
+            stricter_abi_and_runtime_constraints,
+            true, // account_data_direct_mapping
+        )
+        .unwrap();
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         assert_eq!(callee_account.get_data(), b"");
         assert_eq!(callee_account.get_data(), b"");
 
 
         // growing beyond address_space_reserved_for_account
         // growing beyond address_space_reserved_for_account
         *caller_account.ref_to_len_in_vm = (7 + MAX_PERMITTED_DATA_INCREASE) as u64;
         *caller_account.ref_to_len_in_vm = (7 + MAX_PERMITTED_DATA_INCREASE) as u64;
-        let result = update_callee_account(&caller_account, callee_account, direct_mapping, true);
-        if direct_mapping {
+        let result = update_callee_account(
+            true, // check_aligned
+            &caller_account,
+            callee_account,
+            stricter_abi_and_runtime_constraints,
+            true, // account_data_direct_mapping
+        );
+        if stricter_abi_and_runtime_constraints {
             assert_matches!(
             assert_matches!(
                 result,
                 result,
                 Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::InvalidRealloc
                 Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::InvalidRealloc
@@ -1751,7 +1826,7 @@ mod tests {
     }
     }
 
 
     #[test_matrix([false, true])]
     #[test_matrix([false, true])]
-    fn test_update_callee_account_data_readonly(direct_mapping: bool) {
+    fn test_update_callee_account_data_readonly(stricter_abi_and_runtime_constraints: bool) {
         let transaction_accounts =
         let transaction_accounts =
             transaction_with_one_readonly_instruction_account(b"foobar".to_vec());
             transaction_with_one_readonly_instruction_account(b"foobar".to_vec());
         let account = transaction_accounts[1].1.clone();
         let account = transaction_accounts[1].1.clone();
@@ -1770,14 +1845,15 @@ mod tests {
         let mut caller_account = mock_caller_account.caller_account();
         let mut caller_account = mock_caller_account.caller_account();
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
 
 
-        // direct mapping does not copy data in update_callee_account()
+        // stricter_abi_and_runtime_constraints does not copy data in update_callee_account()
         caller_account.serialized_data[0] = b'b';
         caller_account.serialized_data[0] = b'b';
         assert_matches!(
         assert_matches!(
             update_callee_account(
             update_callee_account(
+                true, // check_aligned
                 &caller_account,
                 &caller_account,
                 callee_account,
                 callee_account,
-                false,
-                true,
+                false, // stricter_abi_and_runtime_constraints
+                false, // account_data_direct_mapping
             ),
             ),
             Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ExternalAccountDataModified
             Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::ExternalAccountDataModified
         );
         );
@@ -1789,10 +1865,11 @@ mod tests {
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         assert_matches!(
         assert_matches!(
             update_callee_account(
             update_callee_account(
+                true, // check_aligned
                 &caller_account,
                 &caller_account,
                 callee_account,
                 callee_account,
-                direct_mapping,
-                true,
+                stricter_abi_and_runtime_constraints,
+                true, // account_data_direct_mapping
             ),
             ),
             Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::AccountDataSizeChanged
             Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::AccountDataSizeChanged
         );
         );
@@ -1804,10 +1881,11 @@ mod tests {
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         let callee_account = borrow_instruction_account!(invoke_context, 0);
         assert_matches!(
         assert_matches!(
             update_callee_account(
             update_callee_account(
+                true, // check_aligned
                 &caller_account,
                 &caller_account,
                 callee_account,
                 callee_account,
-                direct_mapping,
-                true,
+                stricter_abi_and_runtime_constraints,
+                true, // account_data_direct_mapping
             ),
             ),
             Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::AccountDataSizeChanged
             Err(error) if error.downcast_ref::<InstructionError>().unwrap() == &InstructionError::AccountDataSizeChanged
         );
         );
@@ -1882,7 +1960,7 @@ mod tests {
         data: Vec<u8>,
         data: Vec<u8>,
         len: u64,
         len: u64,
         regions: Vec<MemoryRegion>,
         regions: Vec<MemoryRegion>,
-        direct_mapping: bool,
+        stricter_abi_and_runtime_constraints: bool,
     }
     }
 
 
     impl MockCallerAccount {
     impl MockCallerAccount {
@@ -1890,12 +1968,12 @@ mod tests {
             lamports: u64,
             lamports: u64,
             owner: Pubkey,
             owner: Pubkey,
             data: &[u8],
             data: &[u8],
-            direct_mapping: bool,
+            stricter_abi_and_runtime_constraints: bool,
         ) -> MockCallerAccount {
         ) -> MockCallerAccount {
             let vm_addr = MM_INPUT_START;
             let vm_addr = MM_INPUT_START;
             let mut region_addr = vm_addr;
             let mut region_addr = vm_addr;
             let region_len = mem::size_of::<u64>()
             let region_len = mem::size_of::<u64>()
-                + if direct_mapping {
+                + if stricter_abi_and_runtime_constraints {
                     0
                     0
                 } else {
                 } else {
                     data.len() + MAX_PERMITTED_DATA_INCREASE
                     data.len() + MAX_PERMITTED_DATA_INCREASE
@@ -1903,19 +1981,19 @@ mod tests {
             let mut d = vec![0; region_len];
             let mut d = vec![0; region_len];
             let mut regions = vec![];
             let mut regions = vec![];
 
 
-            // always write the [len] part even when direct mapping
+            // always write the [len] part even when stricter_abi_and_runtime_constraints
             unsafe { ptr::write_unaligned::<u64>(d.as_mut_ptr().cast(), data.len() as u64) };
             unsafe { ptr::write_unaligned::<u64>(d.as_mut_ptr().cast(), data.len() as u64) };
 
 
-            // write the account data when not direct mapping
-            if !direct_mapping {
+            // write the account data when not stricter_abi_and_runtime_constraints
+            if !stricter_abi_and_runtime_constraints {
                 d[mem::size_of::<u64>()..][..data.len()].copy_from_slice(data);
                 d[mem::size_of::<u64>()..][..data.len()].copy_from_slice(data);
             }
             }
 
 
-            // create a region for [len][data+realloc if !direct_mapping]
+            // create a region for [len][data+realloc if !stricter_abi_and_runtime_constraints]
             regions.push(MemoryRegion::new_writable(&mut d[..region_len], vm_addr));
             regions.push(MemoryRegion::new_writable(&mut d[..region_len], vm_addr));
             region_addr += region_len as u64;
             region_addr += region_len as u64;
 
 
-            if direct_mapping {
+            if stricter_abi_and_runtime_constraints {
                 // create a region for the directly mapped data
                 // create a region for the directly mapped data
                 regions.push(MemoryRegion::new_readonly(data, region_addr));
                 regions.push(MemoryRegion::new_readonly(data, region_addr));
                 region_addr += data.len() as u64;
                 region_addr += data.len() as u64;
@@ -1937,7 +2015,7 @@ mod tests {
                 data: d,
                 data: d,
                 len: data.len() as u64,
                 len: data.len() as u64,
                 regions,
                 regions,
-                direct_mapping,
+                stricter_abi_and_runtime_constraints,
             }
             }
         }
         }
 
 
@@ -1952,7 +2030,7 @@ mod tests {
         }
         }
 
 
         fn caller_account(&mut self) -> CallerAccount {
         fn caller_account(&mut self) -> CallerAccount {
-            let data = if self.direct_mapping {
+            let data = if self.stricter_abi_and_runtime_constraints {
                 &mut []
                 &mut []
             } else {
             } else {
                 &mut self.data[mem::size_of::<u64>()..]
                 &mut self.data[mem::size_of::<u64>()..]

+ 1 - 1
syscalls/src/lib.rs

@@ -345,7 +345,7 @@ pub fn create_program_runtime_environment_v1<'a>(
         sanitize_user_provided_values: true,
         sanitize_user_provided_values: true,
         enabled_sbpf_versions: min_sbpf_version..=max_sbpf_version,
         enabled_sbpf_versions: min_sbpf_version..=max_sbpf_version,
         optimize_rodata: false,
         optimize_rodata: false,
-        aligned_memory_mapping: !feature_set.bpf_account_data_direct_mapping,
+        aligned_memory_mapping: !feature_set.stricter_abi_and_runtime_constraints,
         // Warning, do not use `Config::default()` so that configuration here is explicit.
         // Warning, do not use `Config::default()` so that configuration here is explicit.
     };
     };
     let mut result = BuiltinProgram::new_loader(config);
     let mut result = BuiltinProgram::new_loader(config);

+ 10 - 4
transaction-context/src/lib.rs

@@ -31,7 +31,7 @@ static_assertions::const_assert_eq!(
 #[cfg(not(target_os = "solana"))]
 #[cfg(not(target_os = "solana"))]
 const MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION: i64 =
 const MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION: i64 =
     MAX_PERMITTED_DATA_LENGTH as i64 * 2;
     MAX_PERMITTED_DATA_LENGTH as i64 * 2;
-// Note: With direct mapping programs can grow accounts faster than they intend to,
+// Note: With stricter_abi_and_runtime_constraints programs can grow accounts faster than they intend to,
 // because the AccessViolationHandler might grow an account up to
 // because the AccessViolationHandler might grow an account up to
 // MAX_PERMITTED_DATA_LENGTH at once.
 // MAX_PERMITTED_DATA_LENGTH at once.
 #[cfg(test)]
 #[cfg(test)]
@@ -526,7 +526,11 @@ impl TransactionContext {
     }
     }
 
 
     /// Returns a new account data write access handler
     /// Returns a new account data write access handler
-    pub fn access_violation_handler(&self) -> AccessViolationHandler {
+    pub fn access_violation_handler(
+        &self,
+        stricter_abi_and_runtime_constraints: bool,
+        account_data_direct_mapping: bool,
+    ) -> AccessViolationHandler {
         let accounts = Rc::clone(&self.accounts);
         let accounts = Rc::clone(&self.accounts);
         Box::new(
         Box::new(
             move |region: &mut MemoryRegion,
             move |region: &mut MemoryRegion,
@@ -595,8 +599,10 @@ impl TransactionContext {
                 }
                 }
 
 
                 // Potentially unshare / make the account shared data unique (CoW logic).
                 // Potentially unshare / make the account shared data unique (CoW logic).
-                region.host_addr = account.data_as_mut_slice().as_mut_ptr() as u64;
-                region.writable = true;
+                if stricter_abi_and_runtime_constraints && account_data_direct_mapping {
+                    region.host_addr = account.data_as_mut_slice().as_mut_ptr() as u64;
+                    region.writable = true;
+                }
             },
             },
         )
         )
     }
     }