| 
									
										
										
										
											2019-05-24 16:21:42 -07:00
										 |  |  | pub mod alloc;
 | 
					
						
							|  |  |  | pub mod allocator_bump;
 | 
					
						
							| 
									
										
										
										
											2018-10-16 16:33:31 -07:00
										 |  |  | pub mod bpf_verifier;
 | 
					
						
							| 
									
										
										
										
											2020-04-30 01:43:11 -07:00
										 |  |  | pub mod syscalls;
 | 
					
						
							| 
									
										
										
										
											2018-10-16 16:33:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 01:43:11 -07:00
										 |  |  | use crate::{bpf_verifier::VerifierError, syscalls::SyscallError};
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  | use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
 | 
					
						
							| 
									
										
										
										
											2018-12-14 20:39:10 -08:00
										 |  |  | use log::*;
 | 
					
						
							| 
									
										
										
										
											2020-02-14 13:59:03 -08:00
										 |  |  | use num_derive::{FromPrimitive, ToPrimitive};
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  | use solana_rbpf::{
 | 
					
						
							|  |  |  |     ebpf::{EbpfError, UserDefinedError},
 | 
					
						
							|  |  |  |     memory_region::MemoryRegion,
 | 
					
						
							|  |  |  |     EbpfVm,
 | 
					
						
							|  |  |  | };
 | 
					
						
							| 
									
										
										
										
											2020-01-02 18:18:56 -08:00
										 |  |  | use solana_sdk::{
 | 
					
						
							|  |  |  |     account::KeyedAccount,
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |     bpf_loader,
 | 
					
						
							| 
									
										
										
										
											2020-01-31 10:58:07 -08:00
										 |  |  |     entrypoint::SUCCESS,
 | 
					
						
							| 
									
										
										
										
											2020-01-02 18:18:56 -08:00
										 |  |  |     instruction::InstructionError,
 | 
					
						
							|  |  |  |     loader_instruction::LoaderInstruction,
 | 
					
						
							| 
									
										
										
										
											2020-02-14 13:59:03 -08:00
										 |  |  |     program_utils::DecodeError,
 | 
					
						
							| 
									
										
										
										
											2020-02-05 12:48:30 -08:00
										 |  |  |     program_utils::{is_executable, limited_deserialize, next_keyed_account},
 | 
					
						
							| 
									
										
										
										
											2020-01-02 18:18:56 -08:00
										 |  |  |     pubkey::Pubkey,
 | 
					
						
							|  |  |  | };
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  | use std::{io::prelude::*, mem};
 | 
					
						
							| 
									
										
										
										
											2020-02-14 13:59:03 -08:00
										 |  |  | use thiserror::Error;
 | 
					
						
							| 
									
										
										
										
											2019-05-24 16:21:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-20 16:32:19 -08:00
										 |  |  | solana_sdk::declare_program!(
 | 
					
						
							| 
									
										
										
										
											2019-12-03 20:55:18 -05:00
										 |  |  |     solana_sdk::bpf_loader::ID,
 | 
					
						
							| 
									
										
										
										
											2019-11-20 16:32:19 -08:00
										 |  |  |     solana_bpf_loader_program,
 | 
					
						
							|  |  |  |     process_instruction
 | 
					
						
							|  |  |  | );
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 13:59:03 -08:00
										 |  |  | #[derive(Error, Debug, Clone, PartialEq, FromPrimitive, ToPrimitive)]
 | 
					
						
							|  |  |  | pub enum BPFLoaderError {
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  |     #[error("failed to create virtual machine")]
 | 
					
						
							|  |  |  |     VirtualMachineCreationFailed = 0x0b9f_0001,
 | 
					
						
							|  |  |  |     #[error("virtual machine failed to run the program to completion")]
 | 
					
						
							|  |  |  |     VirtualMachineFailedToRunProgram = 0x0b9f_0002,
 | 
					
						
							| 
									
										
										
										
											2020-02-14 13:59:03 -08:00
										 |  |  | }
 | 
					
						
							|  |  |  | impl<E> DecodeError<E> for BPFLoaderError {
 | 
					
						
							|  |  |  |     fn type_of() -> &'static str {
 | 
					
						
							|  |  |  |         "BPFLoaderError"
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  | /// Errors returned by functions the BPF Loader registers with the vM
 | 
					
						
							|  |  |  | #[derive(Debug, Error)]
 | 
					
						
							|  |  |  | pub enum BPFError {
 | 
					
						
							|  |  |  |     #[error("{0}")]
 | 
					
						
							|  |  |  |     VerifierError(#[from] VerifierError),
 | 
					
						
							|  |  |  |     #[error("{0}")]
 | 
					
						
							| 
									
										
										
										
											2020-04-30 01:43:11 -07:00
										 |  |  |     SyscallError(#[from] SyscallError),
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | impl UserDefinedError for BPFError {}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pub fn create_vm(prog: &[u8]) -> Result<(EbpfVm<BPFError>, MemoryRegion), EbpfError<BPFError>> {
 | 
					
						
							| 
									
										
										
										
											2019-08-23 11:03:53 -07:00
										 |  |  |     let mut vm = EbpfVm::new(None)?;
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:38:07 -07:00
										 |  |  |     vm.set_verifier(bpf_verifier::check)?;
 | 
					
						
							| 
									
										
										
										
											2019-10-02 10:07:44 -07:00
										 |  |  |     vm.set_max_instruction_count(100_000)?;
 | 
					
						
							| 
									
										
										
										
											2018-11-06 14:28:46 -08:00
										 |  |  |     vm.set_elf(&prog)?;
 | 
					
						
							| 
									
										
										
										
											2019-05-24 16:21:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 01:43:11 -07:00
										 |  |  |     let heap_region = syscalls::register_syscalls(&mut vm)?;
 | 
					
						
							| 
									
										
										
										
											2019-05-24 16:21:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Ok((vm, heap_region))
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:38:07 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  | pub fn check_elf(prog: &[u8]) -> Result<(), EbpfError<BPFError>> {
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:03:29 -08:00
										 |  |  |     let mut vm = EbpfVm::new(None)?;
 | 
					
						
							|  |  |  |     vm.set_verifier(bpf_verifier::check)?;
 | 
					
						
							|  |  |  |     vm.set_elf(&prog)?;
 | 
					
						
							|  |  |  |     Ok(())
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  | /// Look for a duplicate account and return its position if found
 | 
					
						
							|  |  |  | pub fn is_dup(accounts: &[KeyedAccount], keyed_account: &KeyedAccount) -> (bool, usize) {
 | 
					
						
							|  |  |  |     for (i, account) in accounts.iter().enumerate() {
 | 
					
						
							|  |  |  |         if account == keyed_account {
 | 
					
						
							|  |  |  |             return (true, i);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     (false, 0)
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-02 18:18:56 -08:00
										 |  |  | pub fn serialize_parameters(
 | 
					
						
							| 
									
										
										
										
											2018-11-17 17:02:14 -08:00
										 |  |  |     program_id: &Pubkey,
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |     keyed_accounts: &[KeyedAccount],
 | 
					
						
							| 
									
										
										
										
											2018-11-13 19:54:41 -08:00
										 |  |  |     data: &[u8],
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  | ) -> Result<Vec<u8>, InstructionError> {
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |     assert_eq!(32, mem::size_of::<Pubkey>());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let mut v: Vec<u8> = Vec::new();
 | 
					
						
							|  |  |  |     v.write_u64::<LittleEndian>(keyed_accounts.len() as u64)
 | 
					
						
							|  |  |  |         .unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |     for (i, keyed_account) in keyed_accounts.iter().enumerate() {
 | 
					
						
							|  |  |  |         let (is_dup, position) = is_dup(&keyed_accounts[..i], keyed_account);
 | 
					
						
							|  |  |  |         if is_dup {
 | 
					
						
							|  |  |  |             v.write_u8(position as u8).unwrap();
 | 
					
						
							|  |  |  |         } else {
 | 
					
						
							| 
									
										
										
										
											2020-02-11 10:03:28 -08:00
										 |  |  |             v.write_u8(std::u8::MAX).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-02-10 21:33:29 -08:00
										 |  |  |             v.write_u8(keyed_account.signer_key().is_some() as u8)
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |                 .unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-02-10 21:33:29 -08:00
										 |  |  |             v.write_u8(keyed_account.is_writable() as u8).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |             v.write_all(keyed_account.unsigned_key().as_ref()).unwrap();
 | 
					
						
							|  |  |  |             v.write_u64::<LittleEndian>(keyed_account.lamports()?)
 | 
					
						
							|  |  |  |                 .unwrap();
 | 
					
						
							|  |  |  |             v.write_u64::<LittleEndian>(keyed_account.data_len()? as u64)
 | 
					
						
							|  |  |  |                 .unwrap();
 | 
					
						
							|  |  |  |             v.write_all(&keyed_account.try_account_ref()?.data).unwrap();
 | 
					
						
							|  |  |  |             v.write_all(keyed_account.owner()?.as_ref()).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-03-04 10:52:09 -08:00
										 |  |  |             v.write_u8(keyed_account.executable()? as u8).unwrap();
 | 
					
						
							|  |  |  |             v.write_u64::<LittleEndian>(keyed_account.rent_epoch()? as u64)
 | 
					
						
							|  |  |  |                 .unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |     }
 | 
					
						
							|  |  |  |     v.write_u64::<LittleEndian>(data.len() as u64).unwrap();
 | 
					
						
							|  |  |  |     v.write_all(data).unwrap();
 | 
					
						
							| 
									
										
										
										
											2018-11-17 17:02:14 -08:00
										 |  |  |     v.write_all(program_id.as_ref()).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |     Ok(v)
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  | pub fn deserialize_parameters(
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |     keyed_accounts: &[KeyedAccount],
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |     buffer: &[u8],
 | 
					
						
							|  |  |  | ) -> Result<(), InstructionError> {
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |     assert_eq!(32, mem::size_of::<Pubkey>());
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |     let mut start = mem::size_of::<u64>(); // number of accounts
 | 
					
						
							| 
									
										
										
										
											2020-01-29 21:49:42 -08:00
										 |  |  |     for (i, keyed_account) in keyed_accounts.iter().enumerate() {
 | 
					
						
							|  |  |  |         let (is_dup, _) = is_dup(&keyed_accounts[..i], keyed_account);
 | 
					
						
							|  |  |  |         start += 1; // is_dup
 | 
					
						
							|  |  |  |         if !is_dup {
 | 
					
						
							| 
									
										
										
										
											2020-02-10 21:33:29 -08:00
										 |  |  |             start += mem::size_of::<u8>(); // is_signer
 | 
					
						
							|  |  |  |             start += mem::size_of::<u8>(); // is_writable
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |             start += mem::size_of::<Pubkey>(); // pubkey
 | 
					
						
							|  |  |  |             keyed_account.try_account_ref_mut()?.lamports =
 | 
					
						
							|  |  |  |                 LittleEndian::read_u64(&buffer[start..]);
 | 
					
						
							|  |  |  |             start += mem::size_of::<u64>() // lamports
 | 
					
						
							|  |  |  |                 + mem::size_of::<u64>(); // data length
 | 
					
						
							|  |  |  |             let end = start + keyed_account.data_len()?;
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |             keyed_account
 | 
					
						
							|  |  |  |                 .try_account_ref_mut()?
 | 
					
						
							|  |  |  |                 .data
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |                 .clone_from_slice(&buffer[start..end]);
 | 
					
						
							|  |  |  |             start += keyed_account.data_len()? // data
 | 
					
						
							| 
									
										
										
										
											2020-03-04 10:52:09 -08:00
										 |  |  |                 + mem::size_of::<Pubkey>() // owner
 | 
					
						
							|  |  |  |                 + mem::size_of::<u8>() // executable
 | 
					
						
							|  |  |  |                 + mem::size_of::<u64>(); // rent_epoch
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |     Ok(())
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-12 08:49:59 -07:00
										 |  |  | pub fn process_instruction(
 | 
					
						
							| 
									
										
										
										
											2018-11-17 17:02:14 -08:00
										 |  |  |     program_id: &Pubkey,
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |     keyed_accounts: &[KeyedAccount],
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |     instruction_data: &[u8],
 | 
					
						
							| 
									
										
										
										
											2019-03-18 10:05:03 -06:00
										 |  |  | ) -> Result<(), InstructionError> {
 | 
					
						
							| 
									
										
										
										
											2020-01-08 09:19:12 -08:00
										 |  |  |     solana_logger::setup_with_default("solana=info");
 | 
					
						
							| 
									
										
										
										
											2018-10-16 16:33:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |     debug_assert!(bpf_loader::check_id(program_id));
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |     if keyed_accounts.is_empty() {
 | 
					
						
							|  |  |  |         warn!("No account keys");
 | 
					
						
							|  |  |  |         return Err(InstructionError::NotEnoughAccountKeys);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |     if is_executable(keyed_accounts)? {
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let mut keyed_accounts_iter = keyed_accounts.iter();
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |         let program = next_keyed_account(&mut keyed_accounts_iter)?;
 | 
					
						
							| 
									
										
										
										
											2020-03-17 12:06:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let parameter_accounts = keyed_accounts_iter.as_slice();
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |         let parameter_bytes = serialize_parameters(
 | 
					
						
							|  |  |  |             program.unsigned_key(),
 | 
					
						
							|  |  |  |             parameter_accounts,
 | 
					
						
							|  |  |  |             &instruction_data,
 | 
					
						
							|  |  |  |         )?;
 | 
					
						
							| 
									
										
										
										
											2020-03-17 12:06:15 -07:00
										 |  |  |         {
 | 
					
						
							|  |  |  |             let program_account = program.try_account_ref_mut()?;
 | 
					
						
							|  |  |  |             let (mut vm, heap_region) = match create_vm(&program_account.data) {
 | 
					
						
							|  |  |  |                 Ok(info) => info,
 | 
					
						
							|  |  |  |                 Err(e) => {
 | 
					
						
							|  |  |  |                     warn!("Failed to create BPF VM: {}", e);
 | 
					
						
							|  |  |  |                     return Err(BPFLoaderError::VirtualMachineCreationFailed.into());
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |             };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             info!("Call BPF program");
 | 
					
						
							|  |  |  |             match vm.execute_program(parameter_bytes.as_slice(), &[], &[heap_region]) {
 | 
					
						
							|  |  |  |                 Ok(status) => {
 | 
					
						
							|  |  |  |                     if status != SUCCESS {
 | 
					
						
							|  |  |  |                         let error: InstructionError = status.into();
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  |                         warn!("BPF program failed: {}", error);
 | 
					
						
							| 
									
										
										
										
											2020-03-17 12:06:15 -07:00
										 |  |  |                         return Err(error);
 | 
					
						
							|  |  |  |                     }
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  |                 Err(error) => {
 | 
					
						
							|  |  |  |                     warn!("BPF program failed: {}", error);
 | 
					
						
							|  |  |  |                     return match error {
 | 
					
						
							| 
									
										
										
										
											2020-04-30 01:43:11 -07:00
										 |  |  |                         EbpfError::UserError(BPFError::SyscallError(
 | 
					
						
							|  |  |  |                             SyscallError::InstructionError(error),
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  |                         )) => Err(error),
 | 
					
						
							|  |  |  |                         _ => Err(BPFLoaderError::VirtualMachineFailedToRunProgram.into()),
 | 
					
						
							|  |  |  |                     };
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |                 }
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         deserialize_parameters(parameter_accounts, ¶meter_bytes)?;
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |         info!("BPF program success");
 | 
					
						
							|  |  |  |     } else if !keyed_accounts.is_empty() {
 | 
					
						
							|  |  |  |         match limited_deserialize(instruction_data)? {
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |             LoaderInstruction::Write { offset, bytes } => {
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |                 let mut keyed_accounts_iter = keyed_accounts.iter();
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |                 let program = next_keyed_account(&mut keyed_accounts_iter)?;
 | 
					
						
							|  |  |  |                 if program.signer_key().is_none() {
 | 
					
						
							| 
									
										
										
										
											2019-07-16 10:45:32 -06:00
										 |  |  |                     warn!("key[0] did not sign the transaction");
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |                     return Err(InstructionError::MissingRequiredSignature);
 | 
					
						
							| 
									
										
										
										
											2019-07-16 10:45:32 -06:00
										 |  |  |                 }
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |                 let offset = offset as usize;
 | 
					
						
							| 
									
										
										
										
											2018-10-19 18:28:38 -07:00
										 |  |  |                 let len = bytes.len();
 | 
					
						
							| 
									
										
										
										
											2019-09-10 16:13:23 -07:00
										 |  |  |                 trace!("Write: offset={} length={}", offset, len);
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |                 if program.data_len()? < offset + len {
 | 
					
						
							|  |  |  |                     warn!("Write overflow: {} < {}", program.data_len()?, offset + len);
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |                     return Err(InstructionError::AccountDataTooSmall);
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |                 }
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |                 program.try_account_ref_mut()?.data[offset..offset + len].copy_from_slice(&bytes);
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |             }
 | 
					
						
							|  |  |  |             LoaderInstruction::Finalize => {
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |                 let mut keyed_accounts_iter = keyed_accounts.iter();
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |                 let program = next_keyed_account(&mut keyed_accounts_iter)?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if program.signer_key().is_none() {
 | 
					
						
							| 
									
										
										
										
											2019-07-16 10:45:32 -06:00
										 |  |  |                     warn!("key[0] did not sign the transaction");
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |                     return Err(InstructionError::MissingRequiredSignature);
 | 
					
						
							| 
									
										
										
										
											2019-07-16 10:45:32 -06:00
										 |  |  |                 }
 | 
					
						
							| 
									
										
										
										
											2019-10-04 02:52:48 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |                 if let Err(e) = check_elf(&program.try_account_ref()?.data) {
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  |                     warn!("{}", e);
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:03:29 -08:00
										 |  |  |                     return Err(InstructionError::InvalidAccountData);
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |                 program.try_account_ref_mut()?.executable = true;
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |                 info!("Finalize: account {:?}", program.signer_key().unwrap());
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2018-12-03 13:32:31 -08:00
										 |  |  |     Ok(())
 | 
					
						
							| 
									
										
										
										
											2018-10-16 09:43:49 -07:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-10-31 10:59:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #[cfg(test)]
 | 
					
						
							|  |  |  | mod tests {
 | 
					
						
							|  |  |  |     use super::*;
 | 
					
						
							| 
									
										
										
										
											2020-05-08 12:37:04 -07:00
										 |  |  |     use rand::Rng;
 | 
					
						
							| 
									
										
										
										
											2020-03-31 11:57:19 -07:00
										 |  |  |     use solana_sdk::{account::Account, rent::Rent};
 | 
					
						
							| 
									
										
										
										
											2020-05-08 12:37:04 -07:00
										 |  |  |     use std::{fs::File, io::Read, ops::Range};
 | 
					
						
							| 
									
										
										
										
											2018-11-06 14:28:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-31 10:59:56 -07:00
										 |  |  |     #[test]
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  |     #[should_panic(expected = "ExceededMaxInstructions(10)")]
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |     fn test_bpf_loader_non_terminating_program() {
 | 
					
						
							| 
									
										
										
										
											2018-10-31 10:59:56 -07:00
										 |  |  |         #[rustfmt::skip]
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         let program = &[
 | 
					
						
							| 
									
										
										
										
											2019-02-22 16:27:19 -08:00
										 |  |  |             0x07, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // r6 + 1
 | 
					
						
							|  |  |  |             0x05, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, // goto -2
 | 
					
						
							| 
									
										
										
										
											2018-10-31 10:59:56 -07:00
										 |  |  |             0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
 | 
					
						
							|  |  |  |         ];
 | 
					
						
							|  |  |  |         let input = &mut [0x00];
 | 
					
						
							| 
									
										
										
										
											2018-11-06 14:28:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 14:00:26 -07:00
										 |  |  |         let mut vm = EbpfVm::<BPFError>::new(None).unwrap();
 | 
					
						
							| 
									
										
										
										
											2018-11-06 14:28:46 -08:00
										 |  |  |         vm.set_verifier(bpf_verifier::check).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-02-22 16:27:19 -08:00
										 |  |  |         vm.set_max_instruction_count(10).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         vm.set_program(program).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-05-24 16:21:42 -07:00
										 |  |  |         vm.execute_program(input, &[], &[]).unwrap();
 | 
					
						
							| 
									
										
										
										
											2018-10-31 10:59:56 -07:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_bpf_loader_write() {
 | 
					
						
							|  |  |  |         let program_id = Pubkey::new_rand();
 | 
					
						
							|  |  |  |         let program_key = Pubkey::new_rand();
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let program_account = Account::new_ref(1, 0, &program_id);
 | 
					
						
							|  |  |  |         let keyed_accounts = vec![KeyedAccount::new(&program_key, false, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |         let instruction_data = bincode::serialize(&LoaderInstruction::Write {
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |             offset: 3,
 | 
					
						
							|  |  |  |             bytes: vec![1, 2, 3],
 | 
					
						
							|  |  |  |         })
 | 
					
						
							|  |  |  |         .unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Case: Empty keyed accounts
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Err(InstructionError::NotEnoughAccountKeys),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &vec![], &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Case: Not signed
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Err(InstructionError::MissingRequiredSignature),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Case: Write bytes to an offset
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let mut keyed_accounts = vec![KeyedAccount::new(&program_key, true, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         keyed_accounts[0].account.borrow_mut().data = vec![0; 6];
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Ok(()),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             vec![0, 0, 0, 1, 2, 3],
 | 
					
						
							|  |  |  |             keyed_accounts[0].account.borrow().data
 | 
					
						
							|  |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Case: Overflow
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let mut keyed_accounts = vec![KeyedAccount::new(&program_key, true, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         keyed_accounts[0].account.borrow_mut().data = vec![0; 5];
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Err(InstructionError::AccountDataTooSmall),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_bpf_loader_finalize() {
 | 
					
						
							|  |  |  |         let program_id = Pubkey::new_rand();
 | 
					
						
							|  |  |  |         let program_key = Pubkey::new_rand();
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:03:29 -08:00
										 |  |  |         let mut file = File::open("test_elfs/noop.so").expect("file open failed");
 | 
					
						
							|  |  |  |         let mut elf = Vec::new();
 | 
					
						
							| 
									
										
										
										
											2020-03-31 11:57:19 -07:00
										 |  |  |         let rent = Rent::default();
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:03:29 -08:00
										 |  |  |         file.read_to_end(&mut elf).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let program_account = Account::new_ref(rent.minimum_balance(elf.len()), 0, &program_id);
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         program_account.borrow_mut().data = elf;
 | 
					
						
							| 
									
										
										
										
											2020-03-31 11:57:19 -07:00
										 |  |  |         let keyed_accounts = vec![KeyedAccount::new(&program_key, false, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |         let instruction_data = bincode::serialize(&LoaderInstruction::Finalize).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Case: Empty keyed accounts
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Err(InstructionError::NotEnoughAccountKeys),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &vec![], &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Case: Not signed
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Err(InstructionError::MissingRequiredSignature),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Case: Finalize
 | 
					
						
							| 
									
										
										
										
											2020-03-31 11:57:19 -07:00
										 |  |  |         let keyed_accounts = vec![KeyedAccount::new(&program_key, true, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Ok(()),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         assert!(keyed_accounts[0].account.borrow().executable);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         program_account.borrow_mut().executable = false; // Un-finalize the account
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:03:29 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Case: Finalize
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         program_account.borrow_mut().data[0] = 0; // bad elf
 | 
					
						
							| 
									
										
										
										
											2020-03-31 11:57:19 -07:00
										 |  |  |         let keyed_accounts = vec![KeyedAccount::new(&program_key, true, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:03:29 -08:00
										 |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Err(InstructionError::InvalidAccountData),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:03:29 -08:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_bpf_loader_invoke_main() {
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         solana_logger::setup();
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         let program_id = Pubkey::new_rand();
 | 
					
						
							|  |  |  |         let program_key = Pubkey::new_rand();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Create program account
 | 
					
						
							|  |  |  |         let mut file = File::open("test_elfs/noop.so").expect("file open failed");
 | 
					
						
							|  |  |  |         let mut elf = Vec::new();
 | 
					
						
							|  |  |  |         file.read_to_end(&mut elf).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let program_account = Account::new_ref(1, 0, &program_id);
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         program_account.borrow_mut().data = elf;
 | 
					
						
							|  |  |  |         program_account.borrow_mut().executable = true;
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let mut keyed_accounts = vec![KeyedAccount::new(&program_key, false, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Case: Empty keyed accounts
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Err(InstructionError::NotEnoughAccountKeys),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &vec![], &vec![])
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Case: Only a program account
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Ok(()),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Case: Account not executable
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         keyed_accounts[0].account.borrow_mut().executable = false;
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         assert_eq!(
 | 
					
						
							| 
									
										
										
										
											2020-01-10 13:20:15 -08:00
										 |  |  |             Err(InstructionError::InvalidInstructionData),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         keyed_accounts[0].account.borrow_mut().executable = true;
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Case: With program and parameter account
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:54:06 -08:00
										 |  |  |         let parameter_account = Account::new_ref(1, 0, &program_id);
 | 
					
						
							|  |  |  |         keyed_accounts.push(KeyedAccount::new(&program_key, false, ¶meter_account));
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Ok(()),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Case: With duplicate accounts
 | 
					
						
							|  |  |  |         let duplicate_key = Pubkey::new_rand();
 | 
					
						
							|  |  |  |         let parameter_account = Account::new_ref(1, 0, &program_id);
 | 
					
						
							| 
									
										
										
										
											2020-02-11 10:03:28 -08:00
										 |  |  |         let mut keyed_accounts = vec![KeyedAccount::new(&program_key, false, &program_account)];
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         keyed_accounts.push(KeyedAccount::new(&duplicate_key, false, ¶meter_account));
 | 
					
						
							|  |  |  |         keyed_accounts.push(KeyedAccount::new(&duplicate_key, false, ¶meter_account));
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             Ok(()),
 | 
					
						
							| 
									
										
										
										
											2020-03-05 10:57:35 -08:00
										 |  |  |             process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2019-11-08 09:19:19 -08:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-05-08 12:37:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// fuzzing utility function
 | 
					
						
							|  |  |  |     fn fuzz<F>(
 | 
					
						
							|  |  |  |         bytes: &[u8],
 | 
					
						
							|  |  |  |         outer_iters: usize,
 | 
					
						
							|  |  |  |         inner_iters: usize,
 | 
					
						
							|  |  |  |         offset: Range<usize>,
 | 
					
						
							|  |  |  |         value: Range<u8>,
 | 
					
						
							|  |  |  |         work: F,
 | 
					
						
							|  |  |  |     ) where
 | 
					
						
							|  |  |  |         F: Fn(&mut [u8]),
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         let mut rng = rand::thread_rng();
 | 
					
						
							|  |  |  |         for _ in 0..outer_iters {
 | 
					
						
							|  |  |  |             let mut mangled_bytes = bytes.to_vec();
 | 
					
						
							|  |  |  |             for _ in 0..inner_iters {
 | 
					
						
							|  |  |  |                 let offset = rng.gen_range(offset.start, offset.end);
 | 
					
						
							|  |  |  |                 let value = rng.gen_range(value.start, value.end);
 | 
					
						
							|  |  |  |                 mangled_bytes[offset] = value;
 | 
					
						
							|  |  |  |                 work(&mut mangled_bytes);
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     #[ignore]
 | 
					
						
							|  |  |  |     fn test_fuzz() {
 | 
					
						
							|  |  |  |         let program_id = Pubkey::new_rand();
 | 
					
						
							|  |  |  |         let program_key = Pubkey::new_rand();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Create program account
 | 
					
						
							|  |  |  |         let mut file = File::open("test_elfs/noop.so").expect("file open failed");
 | 
					
						
							|  |  |  |         let mut elf = Vec::new();
 | 
					
						
							|  |  |  |         file.read_to_end(&mut elf).unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         info!("mangle the whole file");
 | 
					
						
							|  |  |  |         fuzz(
 | 
					
						
							|  |  |  |             &elf,
 | 
					
						
							|  |  |  |             1_000_000_000,
 | 
					
						
							|  |  |  |             100,
 | 
					
						
							|  |  |  |             0..elf.len(),
 | 
					
						
							|  |  |  |             0..255,
 | 
					
						
							|  |  |  |             |bytes: &mut [u8]| {
 | 
					
						
							|  |  |  |                 let program_account = Account::new_ref(1, 0, &program_id);
 | 
					
						
							|  |  |  |                 program_account.borrow_mut().data = bytes.to_vec();
 | 
					
						
							|  |  |  |                 program_account.borrow_mut().executable = true;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 let parameter_account = Account::new_ref(1, 0, &program_id);
 | 
					
						
							|  |  |  |                 let keyed_accounts = vec![
 | 
					
						
							|  |  |  |                     KeyedAccount::new(&program_key, false, &program_account),
 | 
					
						
							|  |  |  |                     KeyedAccount::new(&program_key, false, ¶meter_account),
 | 
					
						
							|  |  |  |                 ];
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 let _result = process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![]);
 | 
					
						
							|  |  |  |             },
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2018-10-31 10:59:56 -07:00
										 |  |  | }
 |