FRET-LibAFL/libafl_qemu/librasan/asan/tests/default_frontend_mock.rs
WorksButNotTested db1d38eeb6
LibAFL_QEMU/librasan: Add support for reading environment (#3241)
* Add support for reading environment

* Fix clippy

* Review fixes
2025-05-20 21:48:08 +02:00

125 lines
3.8 KiB
Rust

extern crate alloc;
#[cfg(test)]
#[cfg(feature = "linux")]
mod tests {
use alloc::alloc::{GlobalAlloc, Layout};
use asan::{
GuestAddr,
allocator::frontend::{AllocatorFrontend, default::DefaultFrontend},
mmap::{Mmap, linux::LinuxMmap},
shadow::{
Shadow,
guest::{DefaultShadowLayout, GuestShadow},
},
tracking::guest::GuestTracking,
};
use log::{debug, info};
use mockall::mock;
use spin::{Lazy, Mutex, MutexGuard};
use thiserror::Error;
const MAX_ADDR: GuestAddr = 64 << 20;
// We can't mock GlobalAlloc since `*mut u8` isn't Send and Sync, so we will
// create a trivial implementation of it which converts the types and calls this
// substititue mockable trait instead.
trait BackendTrait {
fn do_alloc(&self, layout: Layout) -> GuestAddr;
fn do_dealloc(&self, addr: GuestAddr, layout: Layout);
}
mock! {
#[derive(Debug)]
pub Backend {}
impl BackendTrait for Backend {
fn do_alloc(&self, layout: Layout) -> GuestAddr;
fn do_dealloc(&self, addr: GuestAddr, layout: Layout);
}
}
unsafe impl GlobalAlloc for MockBackend {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
self.do_alloc(layout) as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
self.do_dealloc(ptr as GuestAddr, layout)
}
}
#[derive(Error, Debug, PartialEq)]
pub enum MockBackendError {}
static INIT_ONCE: Lazy<Mutex<DF>> = Lazy::new(|| {
Mutex::new({
env_logger::init();
let backend = MockBackend::new();
let shadow = GuestShadow::<LinuxMmap, DefaultShadowLayout>::new().unwrap();
let tracking = GuestTracking::new().unwrap();
DF::new(
backend,
shadow,
tracking,
DF::DEFAULT_REDZONE_SIZE,
DF::DEFAULT_QUARANTINE_SIZE,
)
.unwrap()
})
});
static MAP: Lazy<LinuxMmap> = Lazy::new(|| LinuxMmap::map(MAX_ADDR).unwrap());
type DF =
DefaultFrontend<MockBackend, GuestShadow<LinuxMmap, DefaultShadowLayout>, GuestTracking>;
fn frontend() -> MutexGuard<'static, DF> {
INIT_ONCE.lock()
}
#[test]
fn test_allocate_is_poisoned() {
let mut frontend = frontend();
let base = MAP.as_slice().as_ptr() as GuestAddr;
info!("base: 0x{:x}", base);
let inputs = [[4, 8, 0], [0x3ff, 0, 0]];
for [len, align, addr] in inputs {
frontend
.backend_mut()
.expect_do_alloc()
.returning(move |layout| {
debug!(
"mock - len: 0x{:x}, align: 0x{:x}",
layout.size(),
layout.align()
);
base + addr
});
frontend
.backend_mut()
.expect_do_dealloc()
.returning(|addr, layout| {
debug!(
"mock - addr: 0x{:x}, len: 0x{:x}, align: 0x{:x}",
addr,
layout.size(),
layout.align()
);
});
let buf = frontend.alloc(len, align).unwrap();
info!("buf: 0x{:x}", buf);
for i in buf - DF::DEFAULT_REDZONE_SIZE..buf + len + DF::DEFAULT_REDZONE_SIZE {
let expected = i < buf || i >= buf + len;
let poisoned = frontend.shadow().is_poison(i, 1).unwrap();
assert_eq!(expected, poisoned);
}
frontend.dealloc(buf).unwrap();
}
}
}