@ -54,7 +54,7 @@ pub trait SyscallStubs: Sync + Send {
|
||||
unsafe fn sol_memcpy(&self, dst: *mut u8, src: *const u8, n: usize) {
|
||||
// cannot be overlapping
|
||||
assert!(
|
||||
!(dst as usize + n > src as usize && src as usize > dst as usize),
|
||||
is_nonoverlapping(src as usize, dst as usize, n),
|
||||
"memcpy does not support overlapping regions"
|
||||
);
|
||||
std::ptr::copy_nonoverlapping(src, dst, n as usize);
|
||||
@ -176,3 +176,35 @@ pub(crate) fn sol_set_return_data(data: &[u8]) {
|
||||
pub(crate) fn sol_log_data(data: &[&[u8]]) {
|
||||
SYSCALL_STUBS.read().unwrap().sol_log_data(data)
|
||||
}
|
||||
|
||||
/// Check that two regions do not overlap.
|
||||
///
|
||||
/// Adapted from libcore, hidden to share with bpf_loader without being part of
|
||||
/// the API surface.
|
||||
#[doc(hidden)]
|
||||
pub fn is_nonoverlapping<N>(src: N, dst: N, count: N) -> bool
|
||||
where
|
||||
N: Ord + std::ops::Sub<Output = N>,
|
||||
<N as std::ops::Sub>::Output: Ord,
|
||||
{
|
||||
let diff = if src > dst { src - dst } else { dst - src };
|
||||
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
|
||||
// they do not overlap.
|
||||
diff >= count
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_is_nonoverlapping() {
|
||||
assert!(is_nonoverlapping(10, 7, 3));
|
||||
assert!(!is_nonoverlapping(10, 8, 3));
|
||||
assert!(!is_nonoverlapping(10, 9, 3));
|
||||
assert!(!is_nonoverlapping(10, 10, 3));
|
||||
assert!(!is_nonoverlapping(10, 11, 3));
|
||||
assert!(!is_nonoverlapping(10, 12, 3));
|
||||
assert!(is_nonoverlapping(10, 13, 3));
|
||||
}
|
||||
}
|
||||
|
@ -263,6 +263,10 @@ pub mod reject_empty_instruction_without_program {
|
||||
solana_sdk::declare_id!("9kdtFSrXHQg3hKkbXkQ6trJ3Ja1xpJ22CTFSNAciEwmL");
|
||||
}
|
||||
|
||||
pub mod fixed_memcpy_nonoverlapping_check {
|
||||
solana_sdk::declare_id!("36PRUK2Dz6HWYdG9SpjeAsF5F3KxnFCakA2BZMbtMhSb");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
@ -323,6 +327,7 @@ lazy_static! {
|
||||
(spl_token_v3_3_0_release::id(), "spl-token v3.3.0 release"),
|
||||
(leave_nonce_on_success::id(), "leave nonce as is on success"),
|
||||
(reject_empty_instruction_without_program::id(), "fail instructions which have native_loader as program_id directly"),
|
||||
(fixed_memcpy_nonoverlapping_check::id(), "use correct check for nonoverlapping regions in memcpy syscall"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
Reference in New Issue
Block a user