2020-10-06 11:03:51 -07:00
|
|
|
//! @brief Example Rust-based BPF that tests out using a custom heap
|
|
|
|
|
2020-10-23 17:22:10 -07:00
|
|
|
use solana_program::{
|
2020-10-06 11:03:51 -07:00
|
|
|
account_info::AccountInfo,
|
|
|
|
entrypoint,
|
|
|
|
entrypoint::{ProgramResult, HEAP_LENGTH, HEAP_START_ADDRESS},
|
2020-11-30 13:28:58 -08:00
|
|
|
msg,
|
2020-10-06 11:03:51 -07:00
|
|
|
pubkey::Pubkey,
|
|
|
|
};
|
|
|
|
use std::{
|
|
|
|
alloc::{alloc, Layout},
|
|
|
|
mem::{align_of, size_of},
|
|
|
|
ptr::null_mut,
|
|
|
|
usize,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Developers can implement their own heap by defining their own
|
|
|
|
/// `#[global_allocator]`. The following implements a dummy for test purposes
|
|
|
|
/// but can be flushed out with whatever the developer sees fit.
|
|
|
|
struct BumpAllocator;
|
|
|
|
unsafe impl std::alloc::GlobalAlloc for BumpAllocator {
|
|
|
|
#[inline]
|
|
|
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
|
|
|
if layout.size() == usize::MAX - 0x42 {
|
|
|
|
// Return test value
|
|
|
|
0x42 as *mut u8
|
|
|
|
} else {
|
|
|
|
const POS_PTR: *mut usize = HEAP_START_ADDRESS as *mut usize;
|
|
|
|
const TOP_ADDRESS: usize = HEAP_START_ADDRESS + HEAP_LENGTH;
|
|
|
|
const BOTTOM_ADDRESS: usize = HEAP_START_ADDRESS + size_of::<*mut u8>();
|
|
|
|
|
|
|
|
let mut pos = *POS_PTR;
|
|
|
|
if pos == 0 {
|
|
|
|
// First time, set starting position
|
|
|
|
pos = TOP_ADDRESS;
|
|
|
|
}
|
|
|
|
pos = pos.saturating_sub(layout.size());
|
|
|
|
pos &= !(layout.align().saturating_sub(1));
|
|
|
|
if pos < BOTTOM_ADDRESS {
|
|
|
|
return null_mut();
|
|
|
|
}
|
|
|
|
*POS_PTR = pos;
|
|
|
|
pos as *mut u8
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[inline]
|
|
|
|
unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
|
|
|
|
// I'm a bump allocator, I don't free
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
|
|
#[global_allocator]
|
|
|
|
static A: BumpAllocator = BumpAllocator;
|
|
|
|
|
|
|
|
entrypoint!(process_instruction);
|
|
|
|
fn process_instruction(
|
|
|
|
_program_id: &Pubkey,
|
|
|
|
_accounts: &[AccountInfo],
|
|
|
|
_instruction_data: &[u8],
|
|
|
|
) -> ProgramResult {
|
2020-11-30 13:28:58 -08:00
|
|
|
msg!("Custom heap");
|
2020-10-06 11:03:51 -07:00
|
|
|
unsafe {
|
|
|
|
let layout = Layout::from_size_align(usize::MAX - 0x42, align_of::<u8>()).unwrap();
|
|
|
|
let ptr = alloc(layout);
|
|
|
|
assert_eq!(ptr as u64, 0x42);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|