use enums, support cmplog map collisions

This commit is contained in:
van Hauser
2021-01-18 20:18:18 +01:00
parent 94a15b8ca7
commit 0b545aaeb4
7 changed files with 282 additions and 123 deletions

View File

@ -38,17 +38,17 @@
#define SHAPE_BYTES(x) (x + 1) #define SHAPE_BYTES(x) (x + 1)
#define CMP_TYPE_INS 0 #define CMP_TYPE_INS 1
#define CMP_TYPE_RTN 1 #define CMP_TYPE_RTN 2
struct cmp_header { struct cmp_header {
unsigned hits : 24; unsigned hits : 24;
unsigned id : 24; unsigned id : 24;
unsigned shape : 5; unsigned shape : 5;
unsigned type : 1; unsigned type : 2;
unsigned attribute : 4; unsigned attribute : 4;
unsigned reserved : 6; unsigned reserved : 5;
} __attribute__((packed)); } __attribute__((packed));

View File

@ -23,8 +23,6 @@
#ifndef _HAVE_CONFIG_H #ifndef _HAVE_CONFIG_H
#define _HAVE_CONFIG_H #define _HAVE_CONFIG_H
#include "types.h"
/* Version string: */ /* Version string: */
// c = release, d = volatile github dev, e = experimental branch // c = release, d = volatile github dev, e = experimental branch

View File

@ -25,12 +25,15 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "config.h"
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;
typedef uint32_t u32; typedef uint32_t u32;
#ifdef WORD_SIZE_64
typedef unsigned __int128 uint128_t; typedef unsigned __int128 uint128_t;
typedef uint128_t u128; typedef uint128_t u128;
#endif
/* Extended forkserver option values */ /* Extended forkserver option values */
@ -59,12 +62,14 @@ typedef uint128_t u128;
typedef unsigned long long u64; typedef unsigned long long u64;
typedef int8_t s8; typedef int8_t s8;
typedef int16_t s16; typedef int16_t s16;
typedef int32_t s32; typedef int32_t s32;
typedef int64_t s64; typedef int64_t s64;
#ifdef WORD_SIZE_64
typedef __int128 int128_t; typedef __int128 int128_t;
typedef int128_t s128; typedef int128_t s128;
#endif
#ifndef MIN #ifndef MIN
#define MIN(a, b) \ #define MIN(a, b) \
@ -119,19 +124,21 @@ typedef int128_t s128;
}) })
// It is impossible to define 128 bit constants, so ... // It is impossible to define 128 bit constants, so ...
#define SWAPN(_x, _l) \ #ifdef WORD_SIZE_64
({ \ #define SWAPN(_x, _l) \
\ ({ \
u128 _res = (_x), _ret; \ \
char *d = (char *)&_ret, *s = (char *)&_res; \ u128 _res = (_x), _ret; \
int i; \ char *d = (char *)&_ret, *s = (char *)&_res; \
for (i = 0; i < 16; i++) \ int i; \
d[15 - i] = s[i]; \ for (i = 0; i < 16; i++) \
u32 sr = 128U - ((_l) << 3U); \ d[15 - i] = s[i]; \
(_ret >>= sr); \ u32 sr = 128U - ((_l) << 3U); \
(u128) _ret; \ (_ret >>= sr); \
\ (u128) _ret; \
}) \
})
#endif
#define SWAPNN(_x, _y, _l) \ #define SWAPNN(_x, _y, _l) \
({ \ ({ \

View File

@ -1218,16 +1218,23 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr) {
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = 0;
} else {
hits = __afl_cmp_map->headers[k].hits++;
}
__afl_cmp_map->headers[k].attribute = attr; __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
// if (!__afl_cmp_map->headers[k].cnt)
// __afl_cmp_map->headers[k].cnt = __afl_cmp_counter++;
__afl_cmp_map->headers[k].shape = 0;
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1; __afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2; __afl_cmp_map->log[k][hits].v1 = arg2;
@ -1242,14 +1249,29 @@ void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = 1;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (!__afl_cmp_map->headers[k].shape) {
__afl_cmp_map->headers[k].shape = 1;
}
}
__afl_cmp_map->headers[k].attribute = attr; __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 1;
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1; __afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2; __afl_cmp_map->log[k][hits].v1 = arg2;
@ -1266,14 +1288,29 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr) {
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = 3;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < 3) {
__afl_cmp_map->headers[k].shape = 3;
}
}
__afl_cmp_map->headers[k].attribute = attr; __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 3;
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1; __afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2; __afl_cmp_map->log[k][hits].v1 = arg2;
@ -1282,7 +1319,7 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr) {
void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) { void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) {
fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr); // fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return; if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
@ -1290,20 +1327,36 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) {
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = 7;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < 7) {
__afl_cmp_map->headers[k].shape = 7;
}
}
__afl_cmp_map->headers[k].attribute = attr; __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 7;
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1; __afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2; __afl_cmp_map->log[k][hits].v1 = arg2;
} }
#ifdef WORD_SIZE_64
// support for u24 to u120 via llvm _ExitInt(). size is in bytes minus 1 // support for u24 to u120 via llvm _ExitInt(). size is in bytes minus 1
void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr, void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
uint8_t size) { uint8_t size) {
@ -1318,14 +1371,29 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = size;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < size) {
__afl_cmp_map->headers[k].shape = size;
}
}
__afl_cmp_map->headers[k].attribute = attr; __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = size;
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = (u64)arg1; __afl_cmp_map->log[k][hits].v0 = (u64)arg1;
__afl_cmp_map->log[k][hits].v1 = (u64)arg2; __afl_cmp_map->log[k][hits].v1 = (u64)arg2;
@ -1347,14 +1415,29 @@ void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = 15;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < 15) {
__afl_cmp_map->headers[k].shape = 15;
}
}
__afl_cmp_map->headers[k].attribute = attr; __afl_cmp_map->headers[k].attribute = attr;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 15;
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = (u64)arg1; __afl_cmp_map->log[k][hits].v0 = (u64)arg1;
__afl_cmp_map->log[k][hits].v1 = (u64)arg2; __afl_cmp_map->log[k][hits].v1 = (u64)arg2;
@ -1363,6 +1446,8 @@ void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
} }
#endif
#if defined(__APPLE__) #if defined(__APPLE__)
#pragma weak __sanitizer_cov_trace_const_cmp1 = __cmplog_ins_hook1 #pragma weak __sanitizer_cov_trace_const_cmp1 = __cmplog_ins_hook1
#pragma weak __sanitizer_cov_trace_const_cmp2 = __cmplog_ins_hook2 #pragma weak __sanitizer_cov_trace_const_cmp2 = __cmplog_ins_hook2
@ -1384,8 +1469,10 @@ void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2)
__attribute__((alias("__cmplog_ins_hook4"))); __attribute__((alias("__cmplog_ins_hook4")));
void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2) void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2)
__attribute__((alias("__cmplog_ins_hook8"))); __attribute__((alias("__cmplog_ins_hook8")));
#ifdef WORD_SIZE_64
void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2) void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2)
__attribute__((alias("__cmplog_ins_hook16"))); __attribute__((alias("__cmplog_ins_hook16")));
#endif
void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2) void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2)
__attribute__((alias("__cmplog_ins_hook1"))); __attribute__((alias("__cmplog_ins_hook1")));
@ -1395,8 +1482,10 @@ void __sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2)
__attribute__((alias("__cmplog_ins_hook4"))); __attribute__((alias("__cmplog_ins_hook4")));
void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2) void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2)
__attribute__((alias("__cmplog_ins_hook8"))); __attribute__((alias("__cmplog_ins_hook8")));
#ifdef WORD_SIZE_64
void __sanitizer_cov_trace_cmp16(uint128_t arg1, uint128_t arg2) void __sanitizer_cov_trace_cmp16(uint128_t arg1, uint128_t arg2)
__attribute__((alias("__cmplog_ins_hook16"))); __attribute__((alias("__cmplog_ins_hook16")));
#endif
#endif /* defined(__APPLE__) */ #endif /* defined(__APPLE__) */
void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
@ -1409,12 +1498,28 @@ void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; u32 hits;
u32 hits = __afl_cmp_map->headers[k].hits; if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 7; __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = 7;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < 7) {
__afl_cmp_map->headers[k].shape = 7;
}
}
__afl_cmp_map->headers[k].attribute = 1;
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = val; __afl_cmp_map->log[k][hits].v0 = val;
@ -1448,12 +1553,26 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN; u32 hits;
u32 hits = __afl_cmp_map->headers[k].hits; if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) {
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 31; __afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
hits = 0;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = 31;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < 31) {
__afl_cmp_map->headers[k].shape = 31;
}
}
hits &= CMP_MAP_RTN_H - 1; hits &= CMP_MAP_RTN_H - 1;
__builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, __builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0,

View File

@ -420,6 +420,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
IRB.CreateCall(cmplogHookIns8, args); IRB.CreateCall(cmplogHookIns8, args);
break; break;
case 128: case 128:
#ifdef WORD_SIZE_64
if (max_size == 128) { if (max_size == 128) {
IRB.CreateCall(cmplogHookIns16, args); IRB.CreateCall(cmplogHookIns16, args);
@ -430,6 +431,9 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
} }
#endif
break;
default:
break; break;
} }

View File

@ -1,7 +1,7 @@
#ifndef AFL_NGRAM_CONFIG_H #ifndef AFL_NGRAM_CONFIG_H
#define AFL_NGRAM_CONFIG_H #define AFL_NGRAM_CONFIG_H
#include "../config.h" #include "types.h"
#if (MAP_SIZE_POW2 <= 16) #if (MAP_SIZE_POW2 <= 16)
typedef u16 PREV_LOC_T; typedef u16 PREV_LOC_T;

View File

@ -33,7 +33,26 @@
#define CMPLOG_INTROSPECTION #define CMPLOG_INTROSPECTION
//#define ARITHMETIC_LESSER_GREATER //#define ARITHMETIC_LESSER_GREATER
///// Colorization // CMP attribute enum
enum {
IS_EQUAL = 1,
IS_GREATER = 2,
IS_LESSER = 4,
IS_FP = 8,
IS_FP_MOD = 16,
IS_INT_MOD = 32
};
// CMPLOG LVL
enum {
LVL1 = 1,
LVL2 = 2,
LVL3 = 4
};
struct range { struct range {
@ -545,8 +564,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
unsigned long long unum; unsigned long long unum;
long long num; long long num;
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl == 3 // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
if (lvl & 4) { if (lvl & LVL3) {
if (afl->queue_cur->is_ascii) { if (afl->queue_cur->is_ascii) {
@ -618,7 +637,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// we only allow this for ascii2integer (above) // we only allow this for ascii2integer (above)
if (unlikely(pattern == o_pattern)) { return 0; } if (unlikely(pattern == o_pattern)) { return 0; }
if ((lvl & 1) || ((lvl & 2) && (attr >= 8 && attr <= 15)) || attr >= 16) { if ((lvl & LVL1) || ((lvl & LVL2) && (attr >= IS_FP && attr < IS_FP_MOD)) ||
attr >= IS_FP_MOD) {
if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) { if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) {
@ -632,8 +652,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// if this is an fcmp (attr & 8 == 8) then do not compare the patterns - // if this is an fcmp (attr & 8 == 8) then do not compare the patterns -
// due to a bug in llvm dynamic float bitcasts do not work :( // due to a bug in llvm dynamic float bitcasts do not work :(
// the value 16 means this is a +- 1.0 test case // the value 16 means this is a +- 1.0 test case
if (its_len >= 8 && if (its_len >= 8 && ((*buf_64 == pattern && *o_buf_64 == o_pattern) ||
((*buf_64 == pattern && *o_buf_64 == o_pattern) || attr >= 16)) { attr >= IS_FP_MOD)) {
u64 tmp_64 = *buf_64; u64 tmp_64 = *buf_64;
*buf_64 = repl; *buf_64 = repl;
@ -674,7 +694,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (its_len >= 4 && if (its_len >= 4 &&
((*buf_32 == (u32)pattern && *o_buf_32 == (u32)o_pattern) || ((*buf_32 == (u32)pattern && *o_buf_32 == (u32)o_pattern) ||
attr >= 16)) { attr >= IS_FP_MOD)) {
u32 tmp_32 = *buf_32; u32 tmp_32 = *buf_32;
*buf_32 = (u32)repl; *buf_32 = (u32)repl;
@ -708,7 +728,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (its_len >= 2 && if (its_len >= 2 &&
((*buf_16 == (u16)pattern && *o_buf_16 == (u16)o_pattern) || ((*buf_16 == (u16)pattern && *o_buf_16 == (u16)o_pattern) ||
attr >= 16)) { attr >= IS_FP_MOD)) {
u16 tmp_16 = *buf_16; u16 tmp_16 = *buf_16;
*buf_16 = (u16)repl; *buf_16 = (u16)repl;
@ -738,7 +758,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (*status != 1) { // u8 if (*status != 1) { // u8
// if (its_len >= 1 && (attr <= 1 || attr >= 8)) // if (its_len >= 1)
// fprintf(stderr, // fprintf(stderr,
// "TestU8: %u>=1 (idx=%u attr=%u) %x==%x %x==%x <= %x<-%x\n", // "TestU8: %u>=1 (idx=%u attr=%u) %x==%x %x==%x <= %x<-%x\n",
// its_len, idx, attr, *buf_8, (u8)pattern, *o_buf_8, // its_len, idx, attr, *buf_8, (u8)pattern, *o_buf_8,
@ -746,7 +766,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (its_len >= 1 && if (its_len >= 1 &&
((*buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) || ((*buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) ||
attr >= 16)) { attr >= IS_FP_MOD)) {
u8 tmp_8 = *buf_8; u8 tmp_8 = *buf_8;
*buf_8 = (u8)repl; *buf_8 = (u8)repl;
@ -769,10 +789,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// in original buffer) // in original buffer)
#ifdef ARITHMETIC_LESSER_GREATER #ifdef ARITHMETIC_LESSER_GREATER
if (lvl < 4) { return 0; } if (lvl < LVL3) { return 0; }
// lesser/greater FP comparison // lesser/greater FP comparison
if ((attr & 6) && (attr >= 8 && attr < 16)) { if ((attr & (IS_LESSER + IS_GREATER)) &&
(attr >= IS_FP && attr < IS_FP_MOD)) {
u64 repl_new; u64 repl_new;
if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) { if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) {
@ -869,7 +890,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
} else if ((attr & 6) && attr < 8) { } else if ((attr & (IS_LESSER + IS_GREATER)) && attr < IS_FP) {
// lesser/greater integer comparison // lesser/greater integer comparison
@ -903,6 +924,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
#ifdef WORD_SIZE_64
static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u128 pattern, u128 repl, u128 o_pattern, u128 pattern, u128 repl, u128 o_pattern,
u128 changed_val, u8 attr, u32 idx, u128 changed_val, u8 attr, u32 idx,
@ -917,15 +940,15 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u8 backup[16]; u8 backup[16];
u32 its_len = MIN(len - idx, taint_len); u32 its_len = MIN(len - idx, taint_len);
u32 shape = h->shape + 1; u32 shape = h->shape + 1;
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
size_t off = 0; size_t off = 0;
#else #else
size_t off = 16 - shape; size_t off = 16 - shape;
#endif #endif
if (its_len >= shape) { if (its_len >= shape) {
#ifdef _DEBUG #ifdef _DEBUG
// fprintf(stderr, "TestUN: %u>=%u (len=%u idx=%u attr=%u off=%lu) (%u) ", // fprintf(stderr, "TestUN: %u>=%u (len=%u idx=%u attr=%u off=%lu) (%u) ",
// its_len, shape, len, idx, attr, off, do_reverse); // its_len, shape, len, idx, attr, off, do_reverse);
u32 i; u32 i;
@ -948,7 +971,7 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
for (i = 0; i < shape; i++) for (i = 0; i < shape; i++)
fprintf(stderr, "%02x", o_r[off + i]); fprintf(stderr, "%02x", o_r[off + i]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
if (!memcmp(ptr, p + off, shape) && !memcmp(o_ptr, o_p + off, shape)) { if (!memcmp(ptr, p + off, shape) && !memcmp(o_ptr, o_p + off, shape)) {
@ -957,15 +980,15 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef COMBINE #ifdef COMBINE
if (*status == 1) { memcpy(cbuf + idx, r, shape); } if (*status == 1) { memcpy(cbuf + idx, r, shape); }
#endif #endif
memcpy(ptr, backup, shape); memcpy(ptr, backup, shape);
#ifdef _DEBUG #ifdef _DEBUG
fprintf(stderr, "Status=%u\n", *status); fprintf(stderr, "Status=%u\n", *status);
#endif #endif
} }
@ -990,6 +1013,8 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
} }
#endif
static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
u8 *b = (u8 *)&v; u8 *b = (u8 *)&v;
@ -1040,21 +1065,22 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
} }
#ifdef WORD_SIZE_64
static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) { static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) {
u8 *b = (u8 *)&v; u8 *b = (u8 *)&v;
u32 k; u32 k;
u8 cons_ff = 0, cons_0 = 0; u8 cons_ff = 0, cons_0 = 0;
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
u32 off = 0; u32 off = 0;
for (k = 0; k < size; ++k) { for (k = 0; k < size; ++k) {
#else #else
u32 off = 16 - size; u32 off = 16 - size;
for (k = 16 - size; k < 16; ++k) { for (k = 16 - size; k < 16; ++k) {
#endif #endif
if (b[k] == 0) { if (b[k] == 0) {
++cons_0; ++cons_0;
@ -1077,6 +1103,8 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) {
} }
#endif
static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u32 lvl, struct tainted *taint) { u32 len, u32 lvl, struct tainted *taint) {
@ -1091,11 +1119,13 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u8 found_one = 0; u8 found_one = 0;
/* loop cmps are useless, detect and ignore them */ /* loop cmps are useless, detect and ignore them */
#ifdef WORD_SIZE_64
u128 s128_v0 = 0, s128_v1 = 0, orig_s128_v0 = 0, orig_s128_v1 = 0; u128 s128_v0 = 0, s128_v1 = 0, orig_s128_v0 = 0, orig_s128_v1 = 0;
u64 s_v0, s_v1; #endif
u8 s_v0_fixed = 1, s_v1_fixed = 1; u64 s_v0, s_v1;
u8 s_v0_inc = 1, s_v1_inc = 1; u8 s_v0_fixed = 1, s_v1_fixed = 1;
u8 s_v0_dec = 1, s_v1_dec = 1; u8 s_v0_inc = 1, s_v1_inc = 1;
u8 s_v0_dec = 1, s_v1_dec = 1;
switch (SHAPE_BYTES(h->shape)) { switch (SHAPE_BYTES(h->shape)) {
@ -1110,7 +1140,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
// FP handling only from lvl 2 onwards // FP handling only from lvl 2 onwards
if ((h->attribute & 8) && lvl < 2) return 0; if ((h->attribute & IS_FP) && lvl < LVL2) return 0;
for (i = 0; i < loggeds; ++i) { for (i = 0; i < loggeds; ++i) {
@ -1162,6 +1192,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
#ifdef WORD_SIZE_64
if (unlikely(is_n)) { if (unlikely(is_n)) {
s128_v0 = ((u128)o->v0) + (((u128)o->v0_128) << 64); s128_v0 = ((u128)o->v0) + (((u128)o->v0_128) << 64);
@ -1171,6 +1202,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
#endif
for (idx = 0; idx < len; ++idx) { for (idx = 0; idx < len; ++idx) {
if (have_taint) { if (have_taint) {
@ -1195,6 +1228,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
status = 0; status = 0;
#ifdef WORD_SIZE_64
if (is_n) { // _ExtInt special case including u128 if (is_n) { // _ExtInt special case including u128
if (s128_v0 != orig_s128_v0 && orig_s128_v0 != orig_s128_v1) { if (s128_v0 != orig_s128_v0 && orig_s128_v0 != orig_s128_v1) {
@ -1239,11 +1273,13 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
#endif
// even for u128 and _ExtInt we do cmp_extend_encoding() because // even for u128 and _ExtInt we do cmp_extend_encoding() because
// if we got here their own special trials failed and it might just be // if we got here their own special trials failed and it might just be
// a cast from e.g. u64 to u128 from the input data. // a cast from e.g. u64 to u128 from the input data.
if ((o->v0 != orig_o->v0 || lvl >= 4) && orig_o->v0 != orig_o->v1) { if ((o->v0 != orig_o->v0 || lvl >= LVL3) && orig_o->v0 != orig_o->v1) {
if (unlikely(cmp_extend_encoding( if (unlikely(cmp_extend_encoding(
afl, h, o->v0, o->v1, orig_o->v0, orig_o->v1, h->attribute, idx, afl, h, o->v0, o->v1, orig_o->v0, orig_o->v1, h->attribute, idx,
@ -1263,7 +1299,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
status = 0; status = 0;
if ((o->v1 != orig_o->v1 || lvl >= 4) && orig_o->v0 != orig_o->v1) { if ((o->v1 != orig_o->v1 || lvl >= LVL3) && orig_o->v0 != orig_o->v1) {
if (unlikely(cmp_extend_encoding( if (unlikely(cmp_extend_encoding(
afl, h, o->v1, o->v0, orig_o->v1, orig_o->v0, h->attribute, idx, afl, h, o->v1, o->v0, orig_o->v1, orig_o->v0, h->attribute, idx,
@ -1521,13 +1557,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} }
// do it manually, forkserver clear only afl->fsrv.trace_bits
memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers));
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; }
memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map));
struct tainted *taint = NULL; struct tainted *taint = NULL;
if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) { if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
@ -1562,8 +1591,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
buf = afl->queue_cur->cmplog_colorinput; buf = afl->queue_cur->cmplog_colorinput;
taint = afl->queue_cur->taint; taint = afl->queue_cur->taint;
// reget the cmplog information
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; }
} }
@ -1583,9 +1610,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u32 cmp_locations = 0; u32 cmp_locations = 0;
#endif #endif
// do it manually, forkserver clear only afl->fsrv.trace_bits // Generate the cmplog data
memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers)); // manually clear the full cmp_map
memset(afl->shm.cmp_map, 0, sizeof(struct cmp_map));
if (unlikely(common_fuzz_cmplog_stuff(afl, orig_buf, len))) { return 1; }
memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map));
// manually clear just the headers
memset(afl->shm.cmp_map->headers, 0, sizeof(struct cmp_header));
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; } if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; }
u64 orig_hit_cnt, new_hit_cnt; u64 orig_hit_cnt, new_hit_cnt;
@ -1602,7 +1633,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u32 cmplog_lvl = afl->cmplog_lvl; u32 cmplog_lvl = afl->cmplog_lvl;
if (!cmplog_done) { if (!cmplog_done) {
lvl = 1; lvl = LVL1;
} else { } else {
@ -1610,8 +1641,8 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} }
if (cmplog_lvl >= 2 && cmplog_done < 2) { lvl += 2; } if (cmplog_lvl >= 2 && cmplog_done < 2) { lvl += LVL2; }
if (cmplog_lvl >= 3 && cmplog_done < 3) { lvl += 4; } if (cmplog_lvl >= 3 && cmplog_done < 3) { lvl += LVL3; }
#ifdef COMBINE #ifdef COMBINE
u8 *cbuf = afl_realloc((void **)&afl->in_scratch_buf, len + 128); u8 *cbuf = afl_realloc((void **)&afl->in_scratch_buf, len + 128);
@ -1668,7 +1699,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} }
} else if (lvl & 1) { } else if (lvl & LVL1) {
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, taint))) { if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, taint))) {