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,7 +15,7 @@ void *__libafl_asan_region_is_poisoned(void *beg, size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma comment( \
|
#pragma comment( \
|
||||||
linker, \
|
linker, \
|
||||||
"/alternatename:__asan_region_is_poisoned=__libafl_asan_region_is_poisoned")
|
"/alternatename:__asan_region_is_poisoned=__libafl_asan_region_is_poisoned")
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#ifdef SANCOV_CMPLOG
|
#ifdef SANCOV_CMPLOG
|
||||||
#include "cmplog.h"
|
#include "cmplog.h"
|
||||||
#include <sanitizer/common_interface_defs.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2) {
|
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);
|
__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 push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
//! Sanitizer Coverage comparison functions
|
//! 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();
|
use crate::CMPLOG_MAP_W;
|
||||||
static mut PCS_END: *const usize = ptr::null();
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
@ -28,73 +31,110 @@ extern "C" {
|
|||||||
/// Trace a switch statement
|
/// Trace a switch statement
|
||||||
pub fn __sanitizer_cov_trace_switch(val: u64, cases: *const u64);
|
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]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) {
|
/// overriding `__sanitizer_weak_hook_strncmp`
|
||||||
// "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C."
|
/// # Safety
|
||||||
assert!(
|
/// this function has raw pointer access
|
||||||
pcs_beg == PCS_BEG || PCS_BEG.is_null(),
|
pub unsafe extern "C" fn __sanitizer_weak_hook_strncmp(
|
||||||
"__sanitizer_cov_pcs_init can be called only once."
|
called_pc: *const c_void,
|
||||||
);
|
s1: *const c_char,
|
||||||
assert!(
|
s2: *const c_char,
|
||||||
pcs_end == PCS_END || PCS_END.is_null(),
|
n: usize,
|
||||||
"__sanitizer_cov_pcs_init can be called only once."
|
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;
|
if c1 == 0 || c2 == 0 {
|
||||||
PCS_END = pcs_end;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
}
|
}
|
||||||
|
actual_len += 1;
|
||||||
/// Returns the address associated with this PC.
|
}
|
||||||
#[must_use]
|
__libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len);
|
||||||
pub fn addr(&self) -> usize {
|
|
||||||
self.addr
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a slice containing the PC table.
|
#[no_mangle]
|
||||||
#[must_use]
|
/// overriding `__sanitizer_weak_hook_strncasecmps`
|
||||||
pub fn sanitizer_cov_pc_table() -> Option<&'static [PcTableEntry]> {
|
/// # Safety
|
||||||
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
|
/// this function has raw pointer access
|
||||||
// there's no TOCTOU issue.
|
pub unsafe extern "C" fn __sanitizer_weak_hook_strncasecmp(
|
||||||
unsafe {
|
called_pc: *const c_void,
|
||||||
if PCS_BEG.is_null() || PCS_END.is_null() {
|
s1: *const c_char,
|
||||||
return None;
|
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;
|
||||||
}
|
}
|
||||||
let len = PCS_END.offset_from(PCS_BEG);
|
actual_len += 1;
|
||||||
assert!(
|
}
|
||||||
len > 0,
|
__libafl_targets_cmplog_routines_len(k, s1 as *const u8, s2 as *const u8, actual_len);
|
||||||
"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(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[rustversion::nightly]
|
||||||
#[cfg(feature = "sancov_ngram4")]
|
#[cfg(feature = "sancov_ngram4")]
|
||||||
use core::simd::num::SimdUint;
|
use core::simd::num::SimdUint;
|
||||||
|
use core::{mem, ptr, slice};
|
||||||
|
|
||||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ctx"))]
|
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ctx"))]
|
||||||
use libafl::executors::{hooks::ExecutorHook, HasObservers};
|
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