Fix cmplog implementation (#2439)

* fix cmplog implementation
only set testcase filepath if filepath is none

* libafl-fuzz: fix minor CI

* add missing fields to AFLppCmpLogOperands

* libafl-fuzz: pin CI AFL version to a commit
fix extended_cmplog_instrumentation

* libafl-fuzz: fix CI

* this should not panic

* aaa

* libafl-fuzz: fix cmplog CI

---------

Co-authored-by: Toka <tokazerkje@outlook.com>
This commit is contained in:
Aarnav 2024-07-25 18:10:21 +02:00 committed by GitHub
parent c857b8dd77
commit 76e1b4cb1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 54 additions and 29 deletions

View File

@ -6,7 +6,7 @@ PROFILE_DIR = {value = "release", condition = {env_not_set = ["PROFILE_DIR"] }}
FUZZER_NAME = 'libafl-fuzz' FUZZER_NAME = 'libafl-fuzz'
FUZZER = '${CARGO_TARGET_DIR}/${PROFILE_DIR}/${FUZZER_NAME}' FUZZER = '${CARGO_TARGET_DIR}/${PROFILE_DIR}/${FUZZER_NAME}'
LLVM_CONFIG = {value = "llvm-config-18", condition = {env_not_set = ["LLVM_CONFIG"] }} LLVM_CONFIG = {value = "llvm-config-18", condition = {env_not_set = ["LLVM_CONFIG"] }}
AFL_VERSION = "4.21c" AFL_VERSION = "db23931e7c1727ddac8691a6241c97b2203ec6fc"
AFL_DIR_NAME= {value = "./AFLplusplus-${AFL_VERSION}"} AFL_DIR_NAME= {value = "./AFLplusplus-${AFL_VERSION}"}
AFL_CC_PATH= {value = "${AFL_DIR_NAME}/afl-clang-fast"} AFL_CC_PATH= {value = "${AFL_DIR_NAME}/afl-clang-fast"}
@ -18,8 +18,8 @@ if [ ! -d "$AFL_DIR_NAME" ]; then
if [ -f "v${AFL_VERSION}.zip" ]; then if [ -f "v${AFL_VERSION}.zip" ]; then
rm v${AFL_VERSION}.zip rm v${AFL_VERSION}.zip
fi fi
wget https://github.com/AFLplusplus/AFLplusplus/archive/refs/tags/v${AFL_VERSION}.zip wget https://github.com/AFLplusplus/AFLplusplus/archive/${AFL_VERSION}.zip
unzip v${AFL_VERSION}.zip unzip ${AFL_VERSION}.zip
cd ${AFL_DIR_NAME} cd ${AFL_DIR_NAME}
LLVM_CONFIG=${LLVM_CONFIG} make LLVM_CONFIG=${LLVM_CONFIG} make
cd .. cd ..
@ -60,9 +60,9 @@ test -d "./test/output/fuzzer_main/crashes" || {
} }
# cmplog TODO: AFL_BENCH_UNTIL_CRASH=1 instead of timeout 15s # cmplog TODO: AFL_BENCH_UNTIL_CRASH=1 instead of timeout 15s
AFL_LLVM_CMPLOG=1 AFL_PATH=${AFL_DIR_NAME} ${AFL_CC_PATH} ./test/test-cmplog.c -o ./test/out-cmplog AFL_LLVM_CMPLOG=1 AFL_PATH=${AFL_DIR_NAME} ${AFL_CC_PATH} ./test/test-cmplog.c -o ./test/out-cmplog
AFL_CORES=1 timeout 15 ${FUZZER} -Z -l 3 -m 0 -V30 -i ./test/seeds_cmplog -o ./test/cmplog-output -c 0 ./test/out-cmplog >>errors 2>&1 AFL_CORES=1 timeout 10 ${FUZZER} -Z -l 3 -m 0 -V30 -i ./test/seeds_cmplog -o ./test/cmplog-output -c 0 ./test/out-cmplog || true
test -n "$( ls ./test/cmplog-output/fuzzer_main/crashes/id:000000* ./test/cmplog-output/hangs/id:000000* 2>/dev/null )" || { test -n "$( ls ./test/cmplog-output/fuzzer_main/crashes/id:0* 2>/dev/null )" || {
echo "no crashes found when running cmplog" echo "No crashes found"
exit 1 exit 1
} }
''' '''
@ -77,7 +77,7 @@ windows_alias = "unsupported"
script_runner="@shell" script_runner="@shell"
script=''' script='''
rm -rf AFLplusplus-${AFL_VERSION} rm -rf AFLplusplus-${AFL_VERSION}
rm v${AFL_VERSION}.zip rm ${AFL_VERSION}.zip
rm -rf ./test/out-instr rm -rf ./test/out-instr
rm -rf ./test/output rm -rf ./test/output
''' '''

View File

@ -413,7 +413,9 @@ where
file_name file_name
}; };
*testcase.file_path_mut() = Some(self.dir_path.join(&file_name)); if testcase.file_path().is_none() {
*testcase.file_path_mut() = Some(self.dir_path.join(&file_name));
}
*testcase.filename_mut() = Some(file_name); *testcase.filename_mut() = Some(file_name);
if self.meta_format.is_some() { if self.meta_format.is_some() {

View File

@ -11,12 +11,7 @@
#define CMPLOG_MAP_H 32 #define CMPLOG_MAP_H 32
#endif #endif
// difference between aflpp and libafl #define CMPLOG_RTN_LEN 32
#ifdef CMPLOG_EXTENDED
#define CMPLOG_RTN_LEN 31
#else
#define CMPLOG_RTN_LEN 32
#endif
#define CMPLOG_MAP_RTN_H \ #define CMPLOG_MAP_RTN_H \
((CMPLOG_MAP_H * sizeof(CmpLogInstruction)) / sizeof(CmpLogRoutine)) ((CMPLOG_MAP_H * sizeof(CmpLogInstruction)) / sizeof(CmpLogRoutine))
@ -57,10 +52,15 @@ typedef struct CmpLogInstruction {
typedef struct CmpLogInstructionExtended { typedef struct CmpLogInstructionExtended {
uint64_t v0; uint64_t v0;
uint64_t v1;
uint64_t v0_128; uint64_t v0_128;
uint64_t v0_256_0; // u256 is unsupported by any compiler for now, so future use
uint64_t v0_256_1;
uint64_t v1;
uint64_t v1_128; uint64_t v1_128;
} CmpLogInstructionExtended; uint64_t v1_256_0;
uint64_t v1_256_1;
uint8_t unused[8];
} __attribute__((packed)) CmpLogInstructionExtended;
typedef struct CmpLogRoutine { typedef struct CmpLogRoutine {
uint8_t v0[CMPLOG_RTN_LEN]; uint8_t v0[CMPLOG_RTN_LEN];
@ -69,10 +69,11 @@ typedef struct CmpLogRoutine {
typedef struct CmpLogRoutineExtended { typedef struct CmpLogRoutineExtended {
uint8_t v0[CMPLOG_RTN_LEN]; uint8_t v0[CMPLOG_RTN_LEN];
uint8_t v0_len;
uint8_t v1[CMPLOG_RTN_LEN]; uint8_t v1[CMPLOG_RTN_LEN];
uint8_t v0_len;
uint8_t v1_len; uint8_t v1_len;
} CmpLogRoutineExtended; uint8_t unused[6];
} __attribute__((packed)) CmpLogRoutineExtended;
typedef struct CmpLogMap { typedef struct CmpLogMap {
CmpLogHeader headers[CMPLOG_MAP_W]; CmpLogHeader headers[CMPLOG_MAP_W];

View File

@ -88,9 +88,14 @@ pub struct CmpLogHeader {
/// comparison size is determined by the `hits` field of the associated `AFLppCmpLogHeader`. /// comparison size is determined by the `hits` field of the associated `AFLppCmpLogHeader`.
pub struct AFLppCmpLogOperands { pub struct AFLppCmpLogOperands {
v0: u64, v0: u64,
v1: u64,
v0_128: u64, v0_128: u64,
v0_256_0: u64,
v0_256_1: u64,
v1: u64,
v1_128: u64, v1_128: u64,
v1_256_0: u64,
v1_256_1: u64,
unused: [u8; 8],
} }
impl AFLppCmpLogOperands { impl AFLppCmpLogOperands {
@ -99,9 +104,14 @@ impl AFLppCmpLogOperands {
pub fn new(v0: u64, v1: u64) -> Self { pub fn new(v0: u64, v1: u64) -> Self {
Self { Self {
v0, v0,
v1,
v0_128: 0, v0_128: 0,
v0_256_0: 0,
v0_256_1: 0,
v1,
v1_128: 0, v1_128: 0,
v1_256_0: 0,
v1_256_1: 0,
unused: [0; 8],
} }
} }
@ -115,9 +125,14 @@ impl AFLppCmpLogOperands {
Self { Self {
v0, v0,
v1,
v0_128, v0_128,
v0_256_0: 0,
v0_256_1: 0,
v1,
v1_128, v1_128,
v1_256_0: 0,
v1_256_1: 0,
unused: [0; 8],
} }
} }
@ -175,10 +190,11 @@ impl AFLppCmpLogOperands {
#[repr(C, packed)] #[repr(C, packed)]
/// Comparison function operands, like for strcmp/memcmp, represented as two byte arrays. /// Comparison function operands, like for strcmp/memcmp, represented as two byte arrays.
pub struct AFLppCmpLogFnOperands { pub struct AFLppCmpLogFnOperands {
v0: [u8; 31], v0: [u8; 32],
v1: [u8; 32],
v0_len: u8, v0_len: u8,
v1: [u8; 31],
v1_len: u8, v1_len: u8,
unused: [u8; 6],
} }
impl AFLppCmpLogFnOperands { impl AFLppCmpLogFnOperands {
@ -188,8 +204,8 @@ impl AFLppCmpLogFnOperands {
let v0_len = v0.len() as u8; let v0_len = v0.len() as u8;
let v1_len = v1.len() as u8; let v1_len = v1.len() as u8;
let mut v0_arr = [0; 31]; let mut v0_arr = [0; 32];
let mut v1_arr = [0; 31]; let mut v1_arr = [0; 32];
v0_arr.copy_from_slice(v0); v0_arr.copy_from_slice(v0);
v1_arr.copy_from_slice(v1); v1_arr.copy_from_slice(v1);
@ -199,12 +215,13 @@ impl AFLppCmpLogFnOperands {
v0_len, v0_len,
v1: v1_arr, v1: v1_arr,
v1_len, v1_len,
unused: [0; 6],
} }
} }
#[must_use] #[must_use]
/// first rtn operand /// first rtn operand
pub fn v0(&self) -> &[u8; 31] { pub fn v0(&self) -> &[u8; 32] {
&self.v0 &self.v0
} }
@ -216,7 +233,7 @@ impl AFLppCmpLogFnOperands {
#[must_use] #[must_use]
/// first rtn operand len /// first rtn operand len
pub fn v1(&self) -> &[u8; 31] { pub fn v1(&self) -> &[u8; 32] {
&self.v1 &self.v1
} }
@ -415,9 +432,14 @@ pub static mut libafl_cmplog_map_extended: AFLppCmpLogMap = AFLppCmpLogMap {
vals: AFLppCmpLogVals { vals: AFLppCmpLogVals {
operands: [[AFLppCmpLogOperands { operands: [[AFLppCmpLogOperands {
v0: 0, v0: 0,
v1: 0,
v0_128: 0, v0_128: 0,
v0_256_0: 0,
v0_256_1: 0,
v1: 0,
v1_128: 0, v1_128: 0,
v1_256_0: 0,
v1_256_1: 0,
unused: [0; 8],
}; CMPLOG_MAP_H]; CMPLOG_MAP_W], }; CMPLOG_MAP_H]; CMPLOG_MAP_W],
}, },
}; };
@ -535,7 +557,7 @@ impl CmpMap for AFLppCmpLogMap {
self.vals.operands[idx][execution].v0, self.vals.operands[idx][execution].v0,
self.vals.operands[idx][execution].v1, self.vals.operands[idx][execution].v1,
))), ))),
// TODO handle 128 bits cmps // TODO handle 128 bits & 256 bits cmps
// other => panic!("Invalid CmpLog shape {}", other), // other => panic!("Invalid CmpLog shape {}", other),
_ => None, _ => None,
} }