Move some C functions to Rust from sancov_cmp.c (#2003)
* some * a * clp * aa * just new line * fix * fxi * fix
This commit is contained in:
parent
90c627a7e7
commit
17aae94efc
@ -15,9 +15,9 @@ void *__libafl_asan_region_is_poisoned(void *beg, size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#pragma comment( \
|
||||
linker, \
|
||||
"/alternatename:__asan_region_is_poisoned=__libafl_asan_region_is_poisoned")
|
||||
#pragma comment( \
|
||||
linker, \
|
||||
"/alternatename:__asan_region_is_poisoned=__libafl_asan_region_is_poisoned")
|
||||
|
||||
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#ifdef SANCOV_CMPLOG
|
||||
#include "cmplog.h"
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
#endif
|
||||
|
||||
void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2) {
|
||||
@ -116,69 +115,6 @@ void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2) {
|
||||
__sanitizer_cov_trace_cmp8(arg1, arg2);
|
||||
}
|
||||
|
||||
#ifdef SANCOV_CMPLOG
|
||||
|
||||
void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1,
|
||||
const void *s2, size_t n, int result) {
|
||||
if (result != 0) {
|
||||
uintptr_t k = (uintptr_t)called_pc;
|
||||
k = (k >> 4) ^ (k << 8);
|
||||
k &= CMPLOG_MAP_W - 1;
|
||||
|
||||
__libafl_targets_cmplog_routines_len(k, s1, s2, MIN(n, 32));
|
||||
}
|
||||
}
|
||||
|
||||
void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1,
|
||||
const char *s2, size_t n, int result) {
|
||||
if (result != 0) {
|
||||
n = MIN(n, 32);
|
||||
|
||||
uintptr_t k = (uintptr_t)called_pc;
|
||||
k = (k >> 4) ^ (k << 8);
|
||||
k &= CMPLOG_MAP_W - 1;
|
||||
|
||||
size_t actual_len;
|
||||
for (actual_len = 0; actual_len < n; actual_len++) {
|
||||
if (s1[actual_len] == 0 || s2[actual_len] == 0) { break; }
|
||||
}
|
||||
|
||||
__libafl_targets_cmplog_routines_len(k, (const uint8_t *)s1,
|
||||
(const uint8_t *)s2, actual_len);
|
||||
}
|
||||
}
|
||||
|
||||
void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,
|
||||
const char *s2, size_t n, int result) {
|
||||
__sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
|
||||
}
|
||||
|
||||
void __sanitizer_weak_hook_strcmp(void *called_pc, const char *s1,
|
||||
const char *s2, int result) {
|
||||
if (result != 0) {
|
||||
uintptr_t k = (uintptr_t)called_pc;
|
||||
k = (k >> 4) ^ (k << 8);
|
||||
k &= CMPLOG_MAP_W - 1;
|
||||
|
||||
size_t actual_len;
|
||||
for (actual_len = 0; actual_len < 32; actual_len++) {
|
||||
if (s1[actual_len] == 0 || s2[actual_len] == 0) { break; }
|
||||
}
|
||||
|
||||
__libafl_targets_cmplog_routines_len(k, (const uint8_t *)s1,
|
||||
(const uint8_t *)s2, actual_len);
|
||||
}
|
||||
}
|
||||
|
||||
void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
|
||||
const char *s2, int result) {
|
||||
__sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
|
||||
}
|
||||
|
||||
// strstr, strcasestr, memmem unhandled
|
||||
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
//! Sanitizer Coverage comparison functions
|
||||
|
||||
use core::{mem, ptr, slice};
|
||||
use core::{
|
||||
cmp,
|
||||
ffi::{c_char, c_int, c_void},
|
||||
ptr,
|
||||
};
|
||||
|
||||
static mut PCS_BEG: *const usize = ptr::null();
|
||||
static mut PCS_END: *const usize = ptr::null();
|
||||
use crate::CMPLOG_MAP_W;
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -28,73 +31,110 @@ extern "C" {
|
||||
/// Trace a switch statement
|
||||
pub fn __sanitizer_cov_trace_switch(val: u64, cases: *const u64);
|
||||
|
||||
/// cmplog internal api
|
||||
pub fn __libafl_targets_cmplog_routines_len(k: usize, s1: *const u8, s2: *const u8, len: usize);
|
||||
}
|
||||
|
||||
/// overriding `__sanitizer_weak_hook_memcmp`
|
||||
/// # Safety
|
||||
/// this function has raw pointer access
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn __sanitizer_weak_hook_memcmp(
|
||||
called_pc: *const c_void,
|
||||
s1: *const c_void,
|
||||
s2: *const c_void,
|
||||
n: usize,
|
||||
result: c_int,
|
||||
) {
|
||||
if result != 0 {
|
||||
let k: usize = called_pc as usize;
|
||||
let k = (k >> 4) ^ (k << 8);
|
||||
let k = k & (CMPLOG_MAP_W - 1);
|
||||
__libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, cmp::min(n, 32));
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) {
|
||||
// "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C."
|
||||
assert!(
|
||||
pcs_beg == PCS_BEG || PCS_BEG.is_null(),
|
||||
"__sanitizer_cov_pcs_init can be called only once."
|
||||
);
|
||||
assert!(
|
||||
pcs_end == PCS_END || PCS_END.is_null(),
|
||||
"__sanitizer_cov_pcs_init can be called only once."
|
||||
);
|
||||
/// overriding `__sanitizer_weak_hook_strncmp`
|
||||
/// # Safety
|
||||
/// this function has raw pointer access
|
||||
pub unsafe extern "C" fn __sanitizer_weak_hook_strncmp(
|
||||
called_pc: *const c_void,
|
||||
s1: *const c_char,
|
||||
s2: *const c_char,
|
||||
n: usize,
|
||||
result: c_int,
|
||||
) {
|
||||
if result != 0 {
|
||||
let n = cmp::min(n, 32);
|
||||
let k: usize = called_pc as usize;
|
||||
let k = (k >> 4) ^ (k << 8);
|
||||
let k = k & (CMPLOG_MAP_W - 1);
|
||||
let mut actual_len = 0;
|
||||
while actual_len < n {
|
||||
let c1 = ptr::read(s1.add(actual_len));
|
||||
let c2 = ptr::read(s2.add(actual_len));
|
||||
|
||||
PCS_BEG = pcs_beg;
|
||||
PCS_END = pcs_end;
|
||||
}
|
||||
|
||||
/// An entry to the `sanitizer_cov` `pc_table`
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PcTableEntry {
|
||||
addr: usize,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PcTableEntry {
|
||||
/// Returns whether the PC corresponds to a function entry point.
|
||||
#[must_use]
|
||||
pub fn is_function_entry(&self) -> bool {
|
||||
self.flags == 0x1
|
||||
}
|
||||
|
||||
/// Returns the address associated with this PC.
|
||||
#[must_use]
|
||||
pub fn addr(&self) -> usize {
|
||||
self.addr
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice containing the PC table.
|
||||
#[must_use]
|
||||
pub fn sanitizer_cov_pc_table() -> Option<&'static [PcTableEntry]> {
|
||||
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
|
||||
// there's no TOCTOU issue.
|
||||
unsafe {
|
||||
if PCS_BEG.is_null() || PCS_END.is_null() {
|
||||
return None;
|
||||
if c1 == 0 || c2 == 0 {
|
||||
break;
|
||||
}
|
||||
actual_len += 1;
|
||||
}
|
||||
let len = PCS_END.offset_from(PCS_BEG);
|
||||
assert!(
|
||||
len > 0,
|
||||
"Invalid PC Table bounds - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
assert_eq!(
|
||||
len % 2,
|
||||
0,
|
||||
"PC Table size is not evens - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
assert_eq!(
|
||||
(PCS_BEG as usize) % mem::align_of::<PcTableEntry>(),
|
||||
0,
|
||||
"Unaligned PC Table - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
Some(slice::from_raw_parts(
|
||||
PCS_BEG as *const PcTableEntry,
|
||||
(len / 2).try_into().unwrap(),
|
||||
))
|
||||
__libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
/// overriding `__sanitizer_weak_hook_strncasecmps`
|
||||
/// # Safety
|
||||
/// this function has raw pointer access
|
||||
pub unsafe extern "C" fn __sanitizer_weak_hook_strncasecmp(
|
||||
called_pc: *const c_void,
|
||||
s1: *const c_char,
|
||||
s2: *const c_char,
|
||||
n: usize,
|
||||
result: c_int,
|
||||
) {
|
||||
__sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
/// overriding `__sanitizer_weak_hook_strcmp`
|
||||
/// # Safety
|
||||
/// this function has raw pointer access
|
||||
pub unsafe extern "C" fn __sanitizer_weak_hook_strcmp(
|
||||
called_pc: *const c_void,
|
||||
s1: *const c_char,
|
||||
s2: *const c_char,
|
||||
result: c_int,
|
||||
) {
|
||||
if result != 0 {
|
||||
let k: usize = called_pc as usize;
|
||||
let k = (k >> 4) ^ (k << 8);
|
||||
let k = k & (CMPLOG_MAP_W - 1);
|
||||
let mut actual_len = 0;
|
||||
while actual_len < 32 {
|
||||
let c1 = ptr::read(s1.add(actual_len));
|
||||
let c2 = ptr::read(s2.add(actual_len));
|
||||
|
||||
if c1 == 0 || c2 == 0 {
|
||||
break;
|
||||
}
|
||||
actual_len += 1;
|
||||
}
|
||||
__libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
/// overriding `__sanitizer_weak_hook_strcmp`
|
||||
/// # Safety
|
||||
/// this function has raw pointer access
|
||||
pub unsafe extern "C" fn __sanitizer_weak_hook_strcasecmp(
|
||||
called_pc: *const c_void,
|
||||
s1: *const c_char,
|
||||
s2: *const c_char,
|
||||
result: c_int,
|
||||
) {
|
||||
__sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#[rustversion::nightly]
|
||||
#[cfg(feature = "sancov_ngram4")]
|
||||
use core::simd::num::SimdUint;
|
||||
use core::{mem, ptr, slice};
|
||||
|
||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ctx"))]
|
||||
use libafl::executors::{hooks::ExecutorHook, HasObservers};
|
||||
@ -282,3 +283,75 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut PCS_BEG: *const usize = ptr::null();
|
||||
static mut PCS_END: *const usize = ptr::null();
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) {
|
||||
// "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C."
|
||||
assert!(
|
||||
pcs_beg == PCS_BEG || PCS_BEG.is_null(),
|
||||
"__sanitizer_cov_pcs_init can be called only once."
|
||||
);
|
||||
assert!(
|
||||
pcs_end == PCS_END || PCS_END.is_null(),
|
||||
"__sanitizer_cov_pcs_init can be called only once."
|
||||
);
|
||||
|
||||
PCS_BEG = pcs_beg;
|
||||
PCS_END = pcs_end;
|
||||
}
|
||||
|
||||
/// An entry to the `sanitizer_cov` `pc_table`
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PcTableEntry {
|
||||
addr: usize,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PcTableEntry {
|
||||
/// Returns whether the PC corresponds to a function entry point.
|
||||
#[must_use]
|
||||
pub fn is_function_entry(&self) -> bool {
|
||||
self.flags == 0x1
|
||||
}
|
||||
|
||||
/// Returns the address associated with this PC.
|
||||
#[must_use]
|
||||
pub fn addr(&self) -> usize {
|
||||
self.addr
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice containing the PC table.
|
||||
#[must_use]
|
||||
pub fn sanitizer_cov_pc_table() -> Option<&'static [PcTableEntry]> {
|
||||
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
|
||||
// there's no TOCTOU issue.
|
||||
unsafe {
|
||||
if PCS_BEG.is_null() || PCS_END.is_null() {
|
||||
return None;
|
||||
}
|
||||
let len = PCS_END.offset_from(PCS_BEG);
|
||||
assert!(
|
||||
len > 0,
|
||||
"Invalid PC Table bounds - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
assert_eq!(
|
||||
len % 2,
|
||||
0,
|
||||
"PC Table size is not evens - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
assert_eq!(
|
||||
(PCS_BEG as usize) % mem::align_of::<PcTableEntry>(),
|
||||
0,
|
||||
"Unaligned PC Table - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
Some(slice::from_raw_parts(
|
||||
PCS_BEG as *const PcTableEntry,
|
||||
(len / 2).try_into().unwrap(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user