diff --git a/programs/bpf_loader/src/syscalls/cpi.rs b/programs/bpf_loader/src/syscalls/cpi.rs index b216324c4..a8baa3833 100644 --- a/programs/bpf_loader/src/syscalls/cpi.rs +++ b/programs/bpf_loader/src/syscalls/cpi.rs @@ -24,6 +24,8 @@ struct CallerAccount<'a> { // the pointer field and ref_to_len_in_vm points to the length field. vm_data_addr: u64, ref_to_len_in_vm: &'a mut u64, + // To be removed once `feature_set::move_serialized_len_ptr_in_cpi` is active everywhere + serialized_len_ptr: *mut u64, executable: bool, rent_epoch: u64, } @@ -55,7 +57,7 @@ impl<'a> CallerAccount<'a> { invoke_context.get_check_aligned(), )?; - let (data, vm_data_addr, ref_to_len_in_vm) = { + let (data, vm_data_addr, ref_to_len_in_vm, serialized_len_ptr) = { // Double translate data out of RefCell let data = *translate_type::<&[u8]>( memory_mapping, @@ -77,6 +79,20 @@ impl<'a> CallerAccount<'a> { 8, )? as *mut u64; let ref_to_len_in_vm = unsafe { &mut *translated }; + let serialized_len_ptr = if invoke_context + .feature_set + .is_active(&feature_set::move_serialized_len_ptr_in_cpi::id()) + { + std::ptr::null_mut() + } else { + let ref_of_len_in_input_buffer = + (data.as_ptr() as *const _ as u64).saturating_sub(8); + translate_type_mut::( + memory_mapping, + ref_of_len_in_input_buffer, + invoke_context.get_check_aligned(), + )? + }; let vm_data_addr = data.as_ptr() as u64; ( translate_slice_mut::( @@ -88,6 +104,7 @@ impl<'a> CallerAccount<'a> { )?, vm_data_addr, ref_to_len_in_vm, + serialized_len_ptr, ) }; @@ -98,6 +115,7 @@ impl<'a> CallerAccount<'a> { data, vm_data_addr, ref_to_len_in_vm, + serialized_len_ptr, executable: account_info.executable, rent_epoch: account_info.rent_epoch, }) @@ -156,6 +174,21 @@ impl<'a> CallerAccount<'a> { )?; let ref_to_len_in_vm = unsafe { &mut *(data_len_addr as *mut u64) }; + let ref_of_len_in_input_buffer = + (account_info.data_addr as *mut u8 as u64).saturating_sub(8); + let serialized_len_ptr = if invoke_context + .feature_set + .is_active(&feature_set::move_serialized_len_ptr_in_cpi::id()) + { + std::ptr::null_mut() + } else { + translate_type_mut::( + memory_mapping, + ref_of_len_in_input_buffer, + invoke_context.get_check_aligned(), + )? + }; + Ok(CallerAccount { lamports, owner, @@ -163,6 +196,7 @@ impl<'a> CallerAccount<'a> { data, vm_data_addr, ref_to_len_in_vm, + serialized_len_ptr, executable: account_info.executable, rent_epoch: account_info.rent_epoch, }) @@ -1049,14 +1083,23 @@ fn update_caller_account( *caller_account.ref_to_len_in_vm = new_len as u64; // this is the len field in the serialized parameters - let serialized_len_ptr = translate_type_mut::( - memory_mapping, - caller_account - .vm_data_addr - .saturating_sub(std::mem::size_of::() as u64), - invoke_context.get_check_aligned(), - )?; - *serialized_len_ptr = new_len as u64; + if invoke_context + .feature_set + .is_active(&feature_set::move_serialized_len_ptr_in_cpi::id()) + { + let serialized_len_ptr = translate_type_mut::( + memory_mapping, + caller_account + .vm_data_addr + .saturating_sub(std::mem::size_of::() as u64), + invoke_context.get_check_aligned(), + )?; + *serialized_len_ptr = new_len as u64; + } else { + unsafe { + *caller_account.serialized_len_ptr = new_len as u64; + } + } } let to_slice = &mut caller_account.data; let from_slice = callee_account @@ -1608,6 +1651,7 @@ mod tests { data, vm_data_addr: self.vm_addr + mem::size_of::() as u64, ref_to_len_in_vm: &mut self.len, + serialized_len_ptr: std::ptr::null_mut(), executable: false, rent_epoch: 0, } diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index 3eaeae024..69e135f20 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -574,6 +574,10 @@ pub mod disable_turbine_fanout_experiments { solana_sdk::declare_id!("Gz1aLrbeQ4Q6PTSafCZcGWZXz91yVRi7ASFzFEr1U4sa"); } +pub mod move_serialized_len_ptr_in_cpi { + solana_sdk::declare_id!("74CoWuBmt3rUVUrCb2JiSTvh6nXyBWUsK4SaMj3CtE3T"); +} + lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -712,6 +716,7 @@ lazy_static! { (commission_updates_only_allowed_in_first_half_of_epoch::id(), "validator commission updates are only allowed in the first half of an epoch #29362"), (enable_turbine_fanout_experiments::id(), "enable turbine fanout experiments #29393"), (disable_turbine_fanout_experiments::id(), "disable turbine fanout experiments #29393"), + (move_serialized_len_ptr_in_cpi::id(), "cpi ignore serialized_len_ptr #29592"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter()