use crate::ffi::dfsan::*;
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int, c_long, c_uint, c_void};
pub type DfsanLabel = u8;
pub type DfsanOrigin = u32;
pub fn union(l1: DfsanLabel, l2: DfsanLabel) -> DfsanLabel {
unsafe { dfsan_union(l1, l2) }
}
pub fn set_label(label: DfsanLabel, addr: *mut c_void, size: usize) {
unsafe {
dfsan_set_label(label, addr, size);
}
}
pub fn add_label(label: DfsanLabel, addr: *mut c_void, size: usize) {
unsafe {
dfsan_add_label(label, addr, size);
}
}
pub fn get_label(data: c_long) -> DfsanLabel {
unsafe { dfsan_get_label(data) }
}
pub fn get_origin(data: c_long) -> DfsanOrigin {
unsafe { dfsan_get_origin(data) }
}
pub fn read_label(addr: *const c_void, size: usize) -> DfsanLabel {
unsafe { dfsan_read_label(addr, size) }
}
pub fn read_origin_of_first_taint(addr: *const c_void, size: usize) -> DfsanOrigin {
unsafe { dfsan_read_origin_of_first_taint(addr, size) }
}
pub fn has_label(label: DfsanLabel, elem: DfsanLabel) -> bool {
unsafe { dfsan_has_label(label, elem) != 0 }
}
pub fn flush() {
unsafe {
dfsan_flush();
}
}
pub fn set_write_callback(
callback: Option<unsafe extern "C" fn(fd: c_int, buf: *const c_void, count: usize)>,
) {
unsafe {
dfsan_set_write_callback(callback);
}
}
pub fn set_conditional_callback(
callback: Option<unsafe extern "C" fn(label: DfsanLabel, origin: DfsanOrigin)>,
) {
unsafe {
dfsan_set_conditional_callback(callback);
}
}
pub fn get_labels_in_signal_conditional() -> DfsanLabel {
unsafe { dfsan_get_labels_in_signal_conditional() }
}
pub fn set_reaches_function_callback(
callback: Option<
unsafe extern "C" fn(
label: DfsanLabel,
origin: DfsanOrigin,
file: *const c_char,
line: c_uint,
function: *const c_char,
),
>,
) {
unsafe {
dfsan_set_reaches_function_callback(callback);
}
}
pub fn get_labels_in_signal_reaches_function() -> DfsanLabel {
unsafe { dfsan_get_labels_in_signal_reaches_function() }
}
pub fn print_origin_trace(addr: *const c_void, description: Option<&str>) {
let description_cstr = description.map(|s| CString::new(s).unwrap());
unsafe {
dfsan_print_origin_trace(
addr,
description_cstr
.as_ref()
.map_or(std::ptr::null(), |s| s.as_ptr()),
);
}
}
pub fn sprint_origin_trace(
addr: *const c_void,
description: Option<&str>,
) -> Result<String, String> {
const BUFFER_SIZE: usize = 1024;
let mut buffer = vec![0 as c_char; BUFFER_SIZE];
let description_cstr = description.map(|s| std::ffi::CString::new(s).unwrap());
unsafe {
let len = dfsan_sprint_origin_trace(
addr,
description_cstr
.as_ref()
.map_or(std::ptr::null(), |s| s.as_ptr()),
buffer.as_mut_ptr(),
BUFFER_SIZE,
);
if len >= BUFFER_SIZE {
buffer.resize(len as usize + 1, 0);
dfsan_sprint_origin_trace(
addr,
description_cstr
.as_ref()
.map_or(std::ptr::null(), |s| s.as_ptr()),
buffer.as_mut_ptr(),
len as usize + 1,
);
}
Ok(CStr::from_ptr(buffer.as_ptr())
.to_string_lossy()
.into_owned())
}
}
pub fn sprint_stack_trace() -> Result<String, String> {
const BUFFER_SIZE: usize = 1024;
let mut buffer = vec![0 as c_char; BUFFER_SIZE];
unsafe {
let len = dfsan_sprint_stack_trace(buffer.as_mut_ptr(), BUFFER_SIZE);
if len >= BUFFER_SIZE {
buffer.resize(len as usize + 1, 0);
dfsan_sprint_stack_trace(buffer.as_mut_ptr(), len as usize + 1);
}
Ok(CStr::from_ptr(buffer.as_ptr())
.to_string_lossy()
.into_owned())
}
}
pub fn get_init_origin(addr: *const c_void) -> DfsanOrigin {
unsafe { dfsan_get_init_origin(addr) }
}
pub fn get_track_origins() -> c_int {
unsafe { dfsan_get_track_origins() }
}