assert-type-assumptions (#23996)
This commit is contained in:
parent
1fb82d7924
commit
37497657c6
|
@ -5434,6 +5434,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"libsecp256k1 0.6.0",
|
||||
"log",
|
||||
"memoffset",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parking_lot 0.12.0",
|
||||
|
|
|
@ -3642,6 +3642,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"libsecp256k1 0.6.0",
|
||||
"log",
|
||||
"memoffset",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parking_lot",
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
extern crate solana_program;
|
||||
use solana_program::{
|
||||
account_info::AccountInfo, bpf_loader, entrypoint::ProgramResult, log::*, msg, pubkey::Pubkey,
|
||||
account_info::AccountInfo, bpf_loader, entrypoint::ProgramResult, log::*, msg,
|
||||
program::check_type_assumptions, pubkey::Pubkey,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -70,6 +71,8 @@ pub fn process_instruction(
|
|||
assert!(1.9986f64 < num && num < 2.0f64);
|
||||
}
|
||||
|
||||
check_type_assumptions();
|
||||
|
||||
sol_log_compute_units();
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1428,7 +1428,7 @@ fn assert_instruction_count() {
|
|||
("sanity", 2378),
|
||||
("sanity++", 2278),
|
||||
("secp256k1_recover", 25383),
|
||||
("sha", 1895),
|
||||
("sha", 1355),
|
||||
("struct_pass", 108),
|
||||
("struct_ret", 122),
|
||||
]);
|
||||
|
@ -1448,9 +1448,9 @@ fn assert_instruction_count() {
|
|||
("solana_bpf_rust_noop", 315),
|
||||
("solana_bpf_rust_param_passing", 146),
|
||||
("solana_bpf_rust_rand", 418),
|
||||
("solana_bpf_rust_sanity", 9128),
|
||||
("solana_bpf_rust_sanity", 52170),
|
||||
("solana_bpf_rust_secp256k1_recover", 25707),
|
||||
("solana_bpf_rust_sha", 27033),
|
||||
("solana_bpf_rust_sha", 25338),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -3541,6 +3541,7 @@ mod tests {
|
|||
bpf_loader,
|
||||
fee_calculator::FeeCalculator,
|
||||
hash::hashv,
|
||||
program::check_type_assumptions,
|
||||
sysvar::{clock::Clock, epoch_schedule::EpochSchedule, rent::Rent},
|
||||
transaction_context::TransactionContext,
|
||||
},
|
||||
|
@ -4906,9 +4907,6 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_check_type_assumptions() {
|
||||
// Code in this file assumes that u64 and usize are the same
|
||||
assert_eq!(size_of::<u64>(), size_of::<usize>());
|
||||
// Code in this file assumes that u8 is byte aligned
|
||||
assert_eq!(1, align_of::<u8>());
|
||||
check_type_assumptions();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ bv = { version = "0.11.1", features = ["serde"] }
|
|||
itertools = "0.10.1"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.14"
|
||||
memoffset = "0.6"
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
rustversion = "1.0.3"
|
||||
|
|
|
@ -138,3 +138,165 @@ pub fn get_return_data() -> Option<(Pubkey, Vec<u8>)> {
|
|||
#[cfg(not(target_arch = "bpf"))]
|
||||
crate::program_stubs::sol_get_return_data()
|
||||
}
|
||||
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
pub fn check_type_assumptions() {
|
||||
extern crate memoffset;
|
||||
use {
|
||||
crate::{clock::Epoch, instruction::AccountMeta},
|
||||
memoffset::offset_of,
|
||||
std::{
|
||||
cell::RefCell,
|
||||
mem::{align_of, size_of},
|
||||
rc::Rc,
|
||||
str::FromStr,
|
||||
},
|
||||
};
|
||||
|
||||
// Code in this file assumes that u64 and usize are the same
|
||||
assert_eq!(size_of::<u64>(), size_of::<usize>());
|
||||
// Code in this file assumes that u8 is byte aligned
|
||||
assert_eq!(1, align_of::<u8>());
|
||||
|
||||
// Enforce Instruction layout
|
||||
{
|
||||
assert_eq!(size_of::<AccountMeta>(), 32 + 1 + 1);
|
||||
|
||||
let pubkey1 = Pubkey::from_str("J9PYCcoKusHyKRMXnBL17VTXC3MVETyqBG2KyLXVv6Ai").unwrap();
|
||||
let pubkey2 = Pubkey::from_str("Hvy4GHgPToZNoENTKjC4mJqpzWWjgTwXrFufKfxYiKkV").unwrap();
|
||||
let pubkey3 = Pubkey::from_str("JDMyRL8rCkae7maCSv47upNuBMFd3Mgos1fz2AvYzVzY").unwrap();
|
||||
let account_meta1 = AccountMeta {
|
||||
pubkey: pubkey2,
|
||||
is_signer: true,
|
||||
is_writable: false,
|
||||
};
|
||||
let account_meta2 = AccountMeta {
|
||||
pubkey: pubkey3,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
};
|
||||
let data = vec![1, 2, 3, 4, 5];
|
||||
let instruction = Instruction {
|
||||
program_id: pubkey1,
|
||||
accounts: vec![account_meta1.clone(), account_meta2.clone()],
|
||||
data: data.clone(),
|
||||
};
|
||||
let instruction_addr = &instruction as *const _ as u64;
|
||||
|
||||
// program id
|
||||
assert_eq!(offset_of!(Instruction, program_id), 48);
|
||||
let pubkey_ptr = (instruction_addr + 48) as *const Pubkey;
|
||||
unsafe {
|
||||
assert_eq!(*pubkey_ptr, pubkey1);
|
||||
}
|
||||
|
||||
// accounts
|
||||
assert_eq!(offset_of!(Instruction, accounts), 0);
|
||||
let accounts_ptr = (instruction_addr) as *const *const AccountMeta;
|
||||
let accounts_cap = (instruction_addr + 8) as *const usize;
|
||||
let accounts_len = (instruction_addr + 16) as *const usize;
|
||||
unsafe {
|
||||
assert_eq!(*accounts_cap, 2);
|
||||
assert_eq!(*accounts_len, 2);
|
||||
let account_meta_ptr = *accounts_ptr;
|
||||
assert_eq!(*account_meta_ptr, account_meta1);
|
||||
assert_eq!(*(account_meta_ptr.offset(1)), account_meta2);
|
||||
}
|
||||
|
||||
// data
|
||||
assert_eq!(offset_of!(Instruction, data), 24);
|
||||
let data_ptr = (instruction_addr + 24) as *const *const [u8; 5];
|
||||
let data_cap = (instruction_addr + 24 + 8) as *const usize;
|
||||
let data_len = (instruction_addr + 24 + 16) as *const usize;
|
||||
unsafe {
|
||||
assert_eq!(*data_cap, 5);
|
||||
|
||||
assert_eq!(*data_len, 5);
|
||||
let u8_ptr = *data_ptr;
|
||||
assert_eq!(*u8_ptr, data[..]);
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce AccountInfo layout
|
||||
{
|
||||
let key = Pubkey::from_str("6o8R9NsUxNskF1MfWM1f265y4w86JYbEwqCmTacdLkHp").unwrap();
|
||||
let mut lamports = 31;
|
||||
let mut data = vec![1, 2, 3, 4, 5];
|
||||
let owner = Pubkey::from_str("2tjK4XyNU54XdN9jokx46QzLybbLVGwQQvTfhcuBXAjR").unwrap();
|
||||
let account_info = AccountInfo {
|
||||
key: &key,
|
||||
is_signer: true,
|
||||
is_writable: false,
|
||||
lamports: Rc::new(RefCell::new(&mut lamports)),
|
||||
data: Rc::new(RefCell::new(&mut data)),
|
||||
owner: &owner,
|
||||
executable: true,
|
||||
rent_epoch: 42,
|
||||
};
|
||||
let account_info_addr = &account_info as *const _ as u64;
|
||||
|
||||
// key
|
||||
assert_eq!(offset_of!(AccountInfo, key), 0);
|
||||
let key_ptr = (account_info_addr) as *const &Pubkey;
|
||||
unsafe {
|
||||
assert_eq!(**key_ptr, key);
|
||||
}
|
||||
|
||||
// is_signer
|
||||
assert_eq!(offset_of!(AccountInfo, is_signer), 40);
|
||||
let is_signer_ptr = (account_info_addr + 40) as *const bool;
|
||||
unsafe {
|
||||
assert!(*is_signer_ptr);
|
||||
}
|
||||
|
||||
// is_writable
|
||||
assert_eq!(offset_of!(AccountInfo, is_writable), 41);
|
||||
let is_writable_ptr = (account_info_addr + 41) as *const bool;
|
||||
unsafe {
|
||||
assert!(!*is_writable_ptr);
|
||||
}
|
||||
|
||||
// lamports
|
||||
assert_eq!(offset_of!(AccountInfo, lamports), 8);
|
||||
let lamports_ptr = (account_info_addr + 8) as *const Rc<RefCell<&mut u64>>;
|
||||
unsafe {
|
||||
assert_eq!(**(*lamports_ptr).as_ptr(), 31);
|
||||
}
|
||||
|
||||
// data
|
||||
assert_eq!(offset_of!(AccountInfo, data), 16);
|
||||
let data_ptr = (account_info_addr + 16) as *const Rc<RefCell<&mut [u8]>>;
|
||||
unsafe {
|
||||
assert_eq!((*(*data_ptr).as_ptr())[..], data[..]);
|
||||
}
|
||||
|
||||
// owner
|
||||
assert_eq!(offset_of!(AccountInfo, owner), 24);
|
||||
let owner_ptr = (account_info_addr + 24) as *const &Pubkey;
|
||||
unsafe {
|
||||
assert_eq!(**owner_ptr, owner);
|
||||
}
|
||||
|
||||
// executable
|
||||
assert_eq!(offset_of!(AccountInfo, executable), 42);
|
||||
let executable_ptr = (account_info_addr + 42) as *const bool;
|
||||
unsafe {
|
||||
assert!(*executable_ptr);
|
||||
}
|
||||
|
||||
// rent_epoch
|
||||
assert_eq!(offset_of!(AccountInfo, rent_epoch), 32);
|
||||
let renbt_epoch_ptr = (account_info_addr + 32) as *const Epoch;
|
||||
unsafe {
|
||||
assert_eq!(*renbt_epoch_ptr, 42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_check_type_assumptions() {
|
||||
super::check_type_assumptions()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue