diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 367ed1dd39..9e7f0e82bc 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -1985,6 +1985,13 @@ dependencies = [ "solana-program", ] +[[package]] +name = "solana-bpf-rust-mem" +version = "1.5.0" +dependencies = [ + "solana-program", +] + [[package]] name = "solana-bpf-rust-noop" version = "1.5.0" diff --git a/programs/bpf/Cargo.toml b/programs/bpf/Cargo.toml index db8c5a613d..a2f548cf67 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -49,6 +49,7 @@ members = [ "rust/iter", "rust/many_args", "rust/many_args_dep", + "rust/mem", "rust/noop", "rust/panic", "rust/param_passing", diff --git a/programs/bpf/build.rs b/programs/bpf/build.rs index 89b8701859..5a048afdb8 100644 --- a/programs/bpf/build.rs +++ b/programs/bpf/build.rs @@ -72,6 +72,7 @@ fn main() { "invoked", "iter", "many_args", + "mem", "noop", "panic", "param_passing", diff --git a/programs/bpf/rust/mem/Cargo.toml b/programs/bpf/rust/mem/Cargo.toml new file mode 100644 index 0000000000..ede855de81 --- /dev/null +++ b/programs/bpf/rust/mem/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "solana-bpf-rust-mem" +version = "1.5.0" +description = "Solana BPF test program written in Rust" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +edition = "2018" + +[dependencies] +solana-program = { path = "../../../../sdk/program", version = "1.5.0" } + +[lib] +name = "solana_bpf_rust_mem" +crate-type = ["cdylib"] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/bpf/rust/mem/Xargo.toml b/programs/bpf/rust/mem/Xargo.toml new file mode 100644 index 0000000000..1744f098ae --- /dev/null +++ b/programs/bpf/rust/mem/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] \ No newline at end of file diff --git a/programs/bpf/rust/mem/src/lib.rs b/programs/bpf/rust/mem/src/lib.rs new file mode 100644 index 0000000000..fe08f6e03e --- /dev/null +++ b/programs/bpf/rust/mem/src/lib.rs @@ -0,0 +1,185 @@ +//! @brief Test builtin mem functions + +#![cfg(target_arch = "bpf")] +#![feature(compiler_builtins_lib)] + +extern crate compiler_builtins; +use solana_program::entrypoint::SUCCESS; + +#[no_mangle] +pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { + unsafe { + // memcpy + let src = &mut [1_u8; 18]; + let dst = &mut [0_u8; 1]; + compiler_builtins::mem::memcpy(&mut src[0] as *mut u8, &mut dst[0] as *mut u8, 1); + assert_eq!(&src[..1], dst); + let dst = &mut [0_u8; 3]; + compiler_builtins::mem::memcpy(&mut src[0] as *mut u8, &mut dst[0] as *mut u8, 3); + assert_eq!(&src[..3], dst); + let dst = &mut [0_u8; 8]; + compiler_builtins::mem::memcpy(&mut src[0] as *mut u8, &mut dst[0] as *mut u8, 8); + assert_eq!(&src[..8], dst); + let dst = &mut [0_u8; 9]; + compiler_builtins::mem::memcpy(&mut src[0] as *mut u8, &mut dst[0] as *mut u8, 9); + assert_eq!(&src[..9], dst); + let dst = &mut [0_u8; 16]; + compiler_builtins::mem::memcpy(&mut src[0] as *mut u8, &mut dst[0] as *mut u8, 16); + assert_eq!(&src[..16], dst); + let dst = &mut [0_u8; 18]; + compiler_builtins::mem::memcpy(&mut src[0] as *mut u8, &mut dst[0] as *mut u8, 18); + assert_eq!(&src[..18], dst); + let dst = &mut [0_u8; 18]; + compiler_builtins::mem::memcpy(&mut src[1] as *mut u8, &mut dst[0] as *mut u8, 17); + assert_eq!(&src[1..], &dst[1..]); + let dst = &mut [0_u8; 18]; + compiler_builtins::mem::memcpy(&mut src[1] as *mut u8, &mut dst[1] as *mut u8, 17); + assert_eq!(&src[1..], &dst[..17]); + + // memmove + let buf = &mut [1_u8, 0]; + compiler_builtins::mem::memmove(&mut buf[0] as *mut u8, &mut buf[1] as *mut u8, 1); + assert_eq!(buf[0], buf[1]); + let buf = &mut [1_u8, 0]; + compiler_builtins::mem::memmove(&mut buf[1] as *mut u8, &mut buf[0] as *mut u8, 1); + assert_eq!(buf[0], buf[1]); + let buf = &mut [1_u8, 1, 1, 0, 0, 0]; + compiler_builtins::mem::memmove(&mut buf[0] as *mut u8, &mut buf[3] as *mut u8, 3); + assert_eq!(buf[..3], buf[3..]); + let buf = &mut [1_u8, 1, 1, 0, 0, 0]; + compiler_builtins::mem::memmove(&mut buf[3] as *mut u8, &mut buf[0] as *mut u8, 3); + assert_eq!(buf[..3], buf[3..]); + let buf = &mut [1_u8, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]; + compiler_builtins::mem::memmove(&mut buf[0] as *mut u8, &mut buf[8] as *mut u8, 8); + assert_eq!(buf[..8], buf[8..]); + let buf = &mut [1_u8, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]; + compiler_builtins::mem::memmove(&mut buf[8] as *mut u8, &mut buf[0] as *mut u8, 8); + assert_eq!(buf[..8], buf[8..]); + let buf = &mut [1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + compiler_builtins::mem::memmove(&mut buf[0] as *mut u8, &mut buf[9] as *mut u8, 9); + assert_eq!(buf[..9], buf[9..]); + let buf = &mut [1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + compiler_builtins::mem::memmove(&mut buf[9] as *mut u8, &mut buf[0] as *mut u8, 9); + assert_eq!(buf[..9], buf[9..]); + let buf = &mut [ + 1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]; + compiler_builtins::mem::memmove(&mut buf[0] as *mut u8, &mut buf[16] as *mut u8, 16); + assert_eq!(buf[..16], buf[16..]); + let buf = &mut [ + 1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]; + compiler_builtins::mem::memmove(&mut buf[16] as *mut u8, &mut buf[0] as *mut u8, 16); + assert_eq!(buf[..16], buf[16..]); + let buf = &mut [ + 1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]; + compiler_builtins::mem::memmove(&mut buf[0] as *mut u8, &mut buf[18] as *mut u8, 18); + assert_eq!(buf[..18], buf[18..]); + let buf = &mut [ + 1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]; + compiler_builtins::mem::memmove(&mut buf[18] as *mut u8, &mut buf[0] as *mut u8, 18); + assert_eq!(buf[..18], buf[18..]); + let buf = &mut [ + 1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]; + compiler_builtins::mem::memmove(&mut buf[1] as *mut u8, &mut buf[18] as *mut u8, 17); + assert_eq!(buf[1..17], buf[18..34]); + let buf = &mut [ + 1_u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]; + compiler_builtins::mem::memmove(&mut buf[19] as *mut u8, &mut buf[1] as *mut u8, 17); + assert_eq!(buf[..17], buf[19..]); + + // memset + let exp = &[1_u8; 18]; + let buf = &mut [0_u8; 18]; + compiler_builtins::mem::memset(&mut buf[0] as *mut u8, 1, 1); + assert_eq!(exp[..1], buf[..1]); + compiler_builtins::mem::memset(&mut buf[0] as *mut u8, 1, 3); + assert_eq!(exp[..3], buf[..3]); + compiler_builtins::mem::memset(&mut buf[0] as *mut u8, 1, 8); + assert_eq!(exp[..8], buf[..8]); + compiler_builtins::mem::memset(&mut buf[0] as *mut u8, 1, 9); + assert_eq!(exp[..9], buf[..9]); + compiler_builtins::mem::memset(&mut buf[0] as *mut u8, 1, 16); + assert_eq!(exp[..16], buf[..16]); + compiler_builtins::mem::memset(&mut buf[0] as *mut u8, 1, 18); + assert_eq!(exp[..18], buf[..18]); + compiler_builtins::mem::memset(&mut buf[1] as *mut u8, 1, 17); + assert_eq!(exp[1..18], buf[1..18]); + + // memcmp + assert_eq!( + -1, + compiler_builtins::mem::memcmp(&[0_u8] as *const u8, &[1_u8] as *const u8, 1) + ); + assert_eq!( + -1, + compiler_builtins::mem::memcmp( + &[0_u8, 0, 0] as *const u8, + &[0_u8, 0, 1] as *const u8, + 3 + ) + ); + assert_eq!( + 0, + compiler_builtins::mem::memcmp( + &[0_u8, 0, 0, 0, 0, 0, 0, 0, 0] as *const u8, + &[0_u8, 0, 0, 0, 0, 0, 0, 0, 0] as *const u8, + 9 + ) + ); + assert_eq!( + -1, + compiler_builtins::mem::memcmp( + &[0_u8, 0, 0, 0, 0, 0, 0, 0, 0] as *const u8, + &[0_u8, 0, 0, 0, 0, 0, 0, 0, 1] as *const u8, + 9 + ) + ); + assert_eq!( + -1, + compiler_builtins::mem::memcmp( + &[0_u8, 0, 0, 0, 0, 0, 0, 0, 0, 0] as *const u8, + &[0_u8, 0, 0, 0, 0, 0, 0, 0, 0, 1] as *const u8, + 10 + ) + ); + assert_eq!( + 0, + compiler_builtins::mem::memcmp(&[0_u8; 8] as *const u8, &[0_u8; 8] as *const u8, 8) + ); + assert_eq!( + -1, + compiler_builtins::mem::memcmp(&[0_u8; 8] as *const u8, &[1_u8; 8] as *const u8, 8) + ); + assert_eq!( + -1, + compiler_builtins::mem::memcmp(&[0_u8; 16] as *const u8, &[1_u8; 16] as *const u8, 16) + ); + assert_eq!( + -1, + compiler_builtins::mem::memcmp(&[0_u8; 18] as *const u8, &[1_u8; 18] as *const u8, 18) + ); + let one = &[0_u8; 18]; + let two = &[1_u8; 18]; + assert_eq!( + -1, + compiler_builtins::mem::memcmp(&one[1] as *const u8, &two[0] as *const u8, 17) + ); + assert_eq!( + -1, + compiler_builtins::mem::memcmp(&one[1] as *const u8, &two[1] as *const u8, 17) + ); + } + + SUCCESS +} diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index f0b3b37b1f..16dd13b112 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -162,6 +162,7 @@ fn test_program_bpf_sanity() { ("solana_bpf_rust_external_spend", false), ("solana_bpf_rust_iter", true), ("solana_bpf_rust_many_args", true), + ("solana_bpf_rust_mem", true), ("solana_bpf_rust_noop", true), ("solana_bpf_rust_panic", false), ("solana_bpf_rust_param_passing", true),