Merge pull request #1141 from AFLplusplus/afl4

cmplog enhancement variant
This commit is contained in:
van Hauser
2021-11-07 14:09:09 +01:00
committed by GitHub
22 changed files with 2892 additions and 1468 deletions

View File

@ -32,7 +32,7 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f
# PROGS intentionally omit afl-as, which gets installed elsewhere. # PROGS intentionally omit afl-as, which gets installed elsewhere.
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config afl-persistent-config SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config afl-persistent-config afl-cc
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8 MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
ASAN_OPTIONS=detect_leaks=0 ASAN_OPTIONS=detect_leaks=0

View File

@ -18,6 +18,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix -n dumb mode (nobody should use this) - fix -n dumb mode (nobody should use this)
- fix stability issue with LTO and cmplog - fix stability issue with LTO and cmplog
- better banner - better banner
- more effective cmplog mode
- more often update the UI when in input2stage mode
- frida_mode: David Carlier added Android support :) - frida_mode: David Carlier added Android support :)
- afl-showmap, afl-tmin and afl-analyze: - afl-showmap, afl-tmin and afl-analyze:
- honor persistent mode for more speed. thanks to dloffre-snl for - honor persistent mode for more speed. thanks to dloffre-snl for

View File

@ -104,9 +104,9 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
gsize x0 = ctx_read_reg(context, ARM64_REG_X0); gsize x0 = ctx_read_reg(context, ARM64_REG_X0);
gsize x1 = ctx_read_reg(context, ARM64_REG_X1); gsize x1 = ctx_read_reg(context, ARM64_REG_X1);
if (((G_MAXULONG - x0) < 32) || ((G_MAXULONG - x1) < 32)) return; if (((G_MAXULONG - x0) < 31) || ((G_MAXULONG - x1) < 31)) return;
if (!cmplog_is_readable(x0, 32) || !cmplog_is_readable(x1, 32)) return; if (!cmplog_is_readable(x0, 31) || !cmplog_is_readable(x1, 31)) return;
void *ptr1 = GSIZE_TO_POINTER(x0); void *ptr1 = GSIZE_TO_POINTER(x0);
void *ptr2 = GSIZE_TO_POINTER(x1); void *ptr2 = GSIZE_TO_POINTER(x1);
@ -116,18 +116,36 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
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; if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) {
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
__afl_cmp_map->headers[k].hits = 0;
}
u32 hits = 0;
if (__afl_cmp_map->headers[k].hits == 0) {
__afl_cmp_map->headers[k].shape = 30;
} else {
hits = __afl_cmp_map->headers[k].hits;
}
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 31; __afl_cmp_map->headers[k].shape = 30;
hits &= CMP_MAP_RTN_H - 1; hits &= CMP_MAP_RTN_H - 1;
((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0_len = 31;
((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1_len = 31;
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1, gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1,
32); 31);
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2, gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2,
32); 31);
} }
@ -193,13 +211,24 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
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; if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS)
__afl_cmp_map->headers[k].hits = 0;
u32 hits = 0;
if (__afl_cmp_map->headers[k].hits == 0) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
__afl_cmp_map->headers[k].shape = (size - 1);
} else {
hits = __afl_cmp_map->headers[k].hits;
}
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = (size - 1);
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = operand1; __afl_cmp_map->log[k][hits].v0 = operand1;
__afl_cmp_map->log[k][hits].v1 = operand2; __afl_cmp_map->log[k][hits].v1 = operand2;

View File

@ -99,9 +99,9 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
gsize rdi = ctx_read_reg(context, X86_REG_RDI); gsize rdi = ctx_read_reg(context, X86_REG_RDI);
gsize rsi = ctx_read_reg(context, X86_REG_RSI); gsize rsi = ctx_read_reg(context, X86_REG_RSI);
if (((G_MAXULONG - rdi) < 32) || ((G_MAXULONG - rsi) < 32)) return; if (((G_MAXULONG - rdi) < 31) || ((G_MAXULONG - rsi) < 31)) return;
if (!cmplog_is_readable(rdi, 32) || !cmplog_is_readable(rsi, 32)) return; if (!cmplog_is_readable(rdi, 31) || !cmplog_is_readable(rsi, 31)) return;
void *ptr1 = GSIZE_TO_POINTER(rdi); void *ptr1 = GSIZE_TO_POINTER(rdi);
void *ptr2 = GSIZE_TO_POINTER(rsi); void *ptr2 = GSIZE_TO_POINTER(rsi);
@ -111,18 +111,34 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
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; if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) {
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
__afl_cmp_map->headers[k].hits = 0;
}
u32 hits = 0;
if (__afl_cmp_map->headers[k].hits == 0) {
__afl_cmp_map->headers[k].shape = 30;
} else {
hits = __afl_cmp_map->headers[k].hits;
}
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 31;
hits &= CMP_MAP_RTN_H - 1; hits &= CMP_MAP_RTN_H - 1;
((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0_len = 31;
((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1_len = 31;
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1, gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1,
32); 31);
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2, gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2,
32); 31);
} }
@ -179,13 +195,23 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 7; k &= CMP_MAP_W - 7;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS; if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS)
__afl_cmp_map->headers[k].hits = 0;
u32 hits = 0;
if (__afl_cmp_map->headers[k].hits == 0) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
__afl_cmp_map->headers[k].shape = (size - 1);
} else {
hits = __afl_cmp_map->headers[k].hits;
}
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = (size - 1);
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = operand1; __afl_cmp_map->log[k][hits].v0 = operand1;
__afl_cmp_map->log[k][hits].v1 = operand2; __afl_cmp_map->log[k][hits].v1 = operand2;

View File

@ -104,9 +104,9 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
gsize arg1 = esp[0]; gsize arg1 = esp[0];
gsize arg2 = esp[1]; gsize arg2 = esp[1];
if (((G_MAXULONG - arg1) < 32) || ((G_MAXULONG - arg2) < 32)) return; if (((G_MAXULONG - arg1) < 31) || ((G_MAXULONG - arg2) < 31)) return;
if (!cmplog_is_readable(arg1, 32) || !cmplog_is_readable(arg2, 32)) return; if (!cmplog_is_readable(arg1, 31) || !cmplog_is_readable(arg2, 31)) return;
void *ptr1 = GSIZE_TO_POINTER(arg1); void *ptr1 = GSIZE_TO_POINTER(arg1);
void *ptr2 = GSIZE_TO_POINTER(arg2); void *ptr2 = GSIZE_TO_POINTER(arg2);
@ -116,18 +116,34 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
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; if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) {
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
__afl_cmp_map->headers[k].hits = 0;
}
u32 hits = 0;
if (__afl_cmp_map->headers[k].hits == 0) {
__afl_cmp_map->headers[k].shape = 30;
} else {
hits = __afl_cmp_map->headers[k].hits;
}
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 31;
hits &= CMP_MAP_RTN_H - 1; hits &= CMP_MAP_RTN_H - 1;
((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0_len = 31;
((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1_len = 31;
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1, gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1,
32); 31);
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2, gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2,
32); 31);
} }
@ -184,13 +200,24 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
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; if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS)
__afl_cmp_map->headers[k].hits = 0;
u32 hits = 0;
if (__afl_cmp_map->headers[k].hits == 0) {
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
__afl_cmp_map->headers[k].shape = (size - 1);
} else {
hits = __afl_cmp_map->headers[k].hits;
}
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = (size - 1);
hits &= CMP_MAP_H - 1; hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = operand1; __afl_cmp_map->log[k][hits].v0 = operand1;
__afl_cmp_map->log[k][hits].v1 = operand2; __afl_cmp_map->log[k][hits].v1 = operand2;

View File

@ -1135,6 +1135,7 @@ void setup_signal_handlers(void);
void save_cmdline(afl_state_t *, u32, char **); void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int); void read_foreign_testcases(afl_state_t *, int);
void write_crash_readme(afl_state_t *afl); void write_crash_readme(afl_state_t *afl);
u8 check_if_text_buf(u8 *buf, u32 len);
/* CmpLog */ /* CmpLog */

View File

@ -48,7 +48,8 @@ struct cmp_header {
unsigned shape : 5; unsigned shape : 5;
unsigned type : 2; unsigned type : 2;
unsigned attribute : 4; unsigned attribute : 4;
unsigned reserved : 5; unsigned overflow : 1;
unsigned reserved : 4;
} __attribute__((packed)); } __attribute__((packed));
@ -59,14 +60,16 @@ struct cmp_operands {
u64 v0_128; u64 v0_128;
u64 v1_128; u64 v1_128;
}; } __attribute__((packed));
struct cmpfn_operands { struct cmpfn_operands {
u8 v0[32]; u8 v0[31];
u8 v1[32]; u8 v0_len;
u8 v1[31];
u8 v1_len;
}; } __attribute__((packed));
typedef struct cmp_operands cmp_map_list[CMP_MAP_H]; typedef struct cmp_operands cmp_map_list[CMP_MAP_H];

View File

@ -267,8 +267,8 @@
(first value), and to keep in memory as candidates. The latter should be much (first value), and to keep in memory as candidates. The latter should be much
higher than the former. */ higher than the former. */
#define USE_AUTO_EXTRAS 128 #define USE_AUTO_EXTRAS 4096
#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 64) #define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 8)
/* Scaling factor for the effector map used to skip some of the more /* Scaling factor for the effector map used to skip some of the more
expensive deterministic steps. The actual divisor is set to expensive deterministic steps. The actual divisor is set to

View File

@ -46,6 +46,8 @@ typedef uint128_t u128;
#define FS_ERROR_SHM_OPEN 4 #define FS_ERROR_SHM_OPEN 4
#define FS_ERROR_SHMAT 8 #define FS_ERROR_SHMAT 8
#define FS_ERROR_MMAP 16 #define FS_ERROR_MMAP 16
#define FS_ERROR_OLD_CMPLOG 32
#define FS_ERROR_OLD_CMPLOG_QEMU 64
/* Reporting options */ /* Reporting options */
#define FS_OPT_ENABLED 0x80000001 #define FS_OPT_ENABLED 0x80000001
@ -53,6 +55,7 @@ typedef uint128_t u128;
#define FS_OPT_SNAPSHOT 0x20000000 #define FS_OPT_SNAPSHOT 0x20000000
#define FS_OPT_AUTODICT 0x10000000 #define FS_OPT_AUTODICT 0x10000000
#define FS_OPT_SHDMEM_FUZZ 0x01000000 #define FS_OPT_SHDMEM_FUZZ 0x01000000
#define FS_OPT_NEWCMPLOG 0x02000000
#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000 #define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000
// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 // FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22
#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1) #define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1)

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,10 @@
#include "cmplog.h" #include "cmplog.h"
#include "llvm-alternative-coverage.h" #include "llvm-alternative-coverage.h"
#define XXH_INLINE_ALL
#include "xxhash.h"
#undef XXH_INLINE_ALL
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
@ -154,6 +158,8 @@ static void at_exit(int signal) {
} }
#define default_hash(a, b) XXH3_64bits(a, b)
/* Uninspired gcc plugin instrumentation */ /* Uninspired gcc plugin instrumentation */
void __afl_trace(const u32 x) { void __afl_trace(const u32 x) {
@ -669,7 +675,7 @@ static void __afl_start_snapshots(void) {
/* Phone home and tell the parent that we're OK. If parent isn't there, /* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */ assume we're not running in forkserver mode and just execute program. */
status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT); status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT | FS_OPT_NEWCMPLOG);
if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ; if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE); status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
@ -935,7 +941,12 @@ static void __afl_start_forkserver(void) {
} }
if (__afl_sharedmem_fuzzing != 0) { status_for_fsrv |= FS_OPT_SHDMEM_FUZZ; } if (__afl_sharedmem_fuzzing != 0) { status_for_fsrv |= FS_OPT_SHDMEM_FUZZ; }
if (status_for_fsrv) { status_for_fsrv |= (FS_OPT_ENABLED); } if (status_for_fsrv) {
status_for_fsrv |= (FS_OPT_ENABLED | FS_OPT_NEWCMPLOG);
}
memcpy(tmp, &status_for_fsrv, 4); memcpy(tmp, &status_for_fsrv, 4);
/* Phone home and tell the parent that we're OK. If parent isn't there, /* Phone home and tell the parent that we're OK. If parent isn't there,
@ -1499,8 +1510,7 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr) {
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return; if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
k &= CMP_MAP_W - 1;
u32 hits; u32 hits;
@ -1530,8 +1540,7 @@ void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return; if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
k &= CMP_MAP_W - 1;
u32 hits; u32 hits;
@ -1569,8 +1578,7 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr) {
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return; if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
k &= CMP_MAP_W - 1;
u32 hits; u32 hits;
@ -1608,8 +1616,7 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) {
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return; if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
k &= CMP_MAP_W - 1;
u32 hits; u32 hits;
@ -1652,8 +1659,7 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return; if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
k &= CMP_MAP_W - 1;
u32 hits; u32 hits;
@ -1696,8 +1702,7 @@ void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
if (likely(!__afl_cmp_map)) return; if (likely(!__afl_cmp_map)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
k &= CMP_MAP_W - 1;
u32 hits; u32 hits;
@ -1802,8 +1807,8 @@ void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
for (uint64_t i = 0; i < cases[0]; i++) { for (uint64_t i = 0; i < cases[0]; i++) {
uintptr_t k = (uintptr_t)__builtin_return_address(0) + i; uintptr_t k = (uintptr_t)__builtin_return_address(0) + i;
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) &
k &= CMP_MAP_W - 1; (CMP_MAP_W - 1));
u32 hits; u32 hits;
@ -1880,6 +1885,159 @@ static int area_is_valid(void *ptr, size_t len) {
} }
void __cmplog_rtn_hook_n(u8 *ptr1, u8 *ptr2, u64 len) {
/*
u32 i;
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
fprintf(stderr, "rtn_n len=%u arg0=", len);
for (i = 0; i < len; i++)
fprintf(stderr, "%02x", ptr1[i]);
fprintf(stderr, " arg1=");
for (i = 0; i < len; i++)
fprintf(stderr, "%02x", ptr2[i]);
fprintf(stderr, "\n");
*/
if (likely(!__afl_cmp_map)) return;
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
if (unlikely(!len)) return;
int l = MIN(31, len);
// fprintf(stderr, "RTN2 %u\n", l);
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) {
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = l - 1;
hits = 0;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < l) {
__afl_cmp_map->headers[k].shape = l - 1;
}
}
struct cmpfn_operands *cmpfn = (struct cmpfn_operands *)__afl_cmp_map->log[k];
hits &= CMP_MAP_RTN_H - 1;
cmpfn[hits].v0_len = l;
cmpfn[hits].v1_len = l;
__builtin_memcpy(cmpfn[hits].v0, ptr1, l);
__builtin_memcpy(cmpfn[hits].v1, ptr2, l);
// fprintf(stderr, "RTN3\n");
}
void __cmplog_rtn_hook_strn(u8 *ptr1, u8 *ptr2, u64 len) {
/*
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
fprintf(stderr, "rtn_strn len=%u arg0=%s arg1=%s\n", len, ptr1, ptr2);
*/
if (likely(!__afl_cmp_map)) return;
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
if (unlikely(!len)) return;
int l = MIN(31, len + 1);
// fprintf(stderr, "RTN2 %u\n", l);
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) {
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = l - 1;
hits = 0;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < l) {
__afl_cmp_map->headers[k].shape = l - 1;
}
}
struct cmpfn_operands *cmpfn = (struct cmpfn_operands *)__afl_cmp_map->log[k];
hits &= CMP_MAP_RTN_H - 1;
cmpfn[hits].v0_len = 0x80 + l;
cmpfn[hits].v1_len = 0x80 + l;
__builtin_memcpy(cmpfn[hits].v0, ptr1, l);
__builtin_memcpy(cmpfn[hits].v1, ptr2, l);
// fprintf(stderr, "RTN3\n");
}
void __cmplog_rtn_hook_str(u8 *ptr1, u8 *ptr2) {
/*
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
fprintf(stderr, "rtn_str arg0=%s arg1=%s\n", ptr1, ptr2);
*/
if (likely(!__afl_cmp_map)) return;
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
if (unlikely(!ptr1 || !ptr2)) return;
int len1 = MIN(31, strlen(ptr1) + 1);
int len2 = MIN(31, strlen(ptr2) + 1);
int l = MIN(MAX(len1, len2), 31);
// fprintf(stderr, "RTN2 %u\n", l);
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
u32 hits;
if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) {
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
__afl_cmp_map->headers[k].hits = 1;
__afl_cmp_map->headers[k].shape = l - 1;
hits = 0;
} else {
hits = __afl_cmp_map->headers[k].hits++;
if (__afl_cmp_map->headers[k].shape < l) {
__afl_cmp_map->headers[k].shape = l - 1;
}
}
struct cmpfn_operands *cmpfn = (struct cmpfn_operands *)__afl_cmp_map->log[k];
hits &= CMP_MAP_RTN_H - 1;
cmpfn[hits].v0_len = 0x80 + len1;
cmpfn[hits].v1_len = 0x80 + len2;
__builtin_memcpy(cmpfn[hits].v0, ptr1, len1);
__builtin_memcpy(cmpfn[hits].v1, ptr2, len2);
// fprintf(stderr, "RTN3\n");
}
void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
/* /*
@ -1900,12 +2058,11 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
if ((l1 = area_is_valid(ptr1, 32)) <= 0 || if ((l1 = area_is_valid(ptr1, 32)) <= 0 ||
(l2 = area_is_valid(ptr2, 32)) <= 0) (l2 = area_is_valid(ptr2, 32)) <= 0)
return; return;
int len = MIN(l1, l2); int len = MIN(31, MIN(l1, l2));
// fprintf(stderr, "RTN2 %u\n", len); // fprintf(stderr, "RTN2 %u\n", len);
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
k &= CMP_MAP_W - 1;
u32 hits; u32 hits;
@ -1928,11 +2085,13 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
} }
struct cmpfn_operands *cmpfn = (struct cmpfn_operands *)__afl_cmp_map->log[k];
hits &= CMP_MAP_RTN_H - 1; hits &= CMP_MAP_RTN_H - 1;
__builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0,
ptr1, len); cmpfn[hits].v0_len = len;
__builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, cmpfn[hits].v1_len = len;
ptr2, len); __builtin_memcpy(cmpfn[hits].v0, ptr1, len);
__builtin_memcpy(cmpfn[hits].v1, ptr2, len);
// fprintf(stderr, "RTN3\n"); // fprintf(stderr, "RTN3\n");
} }

View File

@ -87,12 +87,14 @@ char CmpLogRoutines::ID = 0;
bool CmpLogRoutines::hookRtns(Module &M) { bool CmpLogRoutines::hookRtns(Module &M) {
std::vector<CallInst *> calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC; std::vector<CallInst *> calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC,
LLVMContext & C = M.getContext(); Memcmp, Strcmp, Strncmp;
LLVMContext &C = M.getContext();
Type *VoidTy = Type::getVoidTy(C); Type *VoidTy = Type::getVoidTy(C);
// PointerType *VoidPtrTy = PointerType::get(VoidTy, 0); // PointerType *VoidPtrTy = PointerType::get(VoidTy, 0);
IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
PointerType *i8PtrTy = PointerType::get(Int8Ty, 0); PointerType *i8PtrTy = PointerType::get(Int8Ty, 0);
#if LLVM_VERSION_MAJOR < 9 #if LLVM_VERSION_MAJOR < 9
@ -184,6 +186,60 @@ bool CmpLogRoutines::hookRtns(Module &M) {
FunctionCallee cmplogGccStdC = c4; FunctionCallee cmplogGccStdC = c4;
#endif #endif
#if LLVM_VERSION_MAJOR < 9
Constant *
#else
FunctionCallee
#endif
c5 = M.getOrInsertFunction("__cmplog_rtn_hook_n", VoidTy, i8PtrTy,
i8PtrTy, Int64Ty
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
Function *cmplogHookFnN = cast<Function>(c5);
#else
FunctionCallee cmplogHookFnN = c5;
#endif
#if LLVM_VERSION_MAJOR < 9
Constant *
#else
FunctionCallee
#endif
c6 = M.getOrInsertFunction("__cmplog_rtn_hook_strn", VoidTy, i8PtrTy,
i8PtrTy, Int64Ty
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
Function *cmplogHookFnStrN = cast<Function>(c6);
#else
FunctionCallee cmplogHookFnStrN = c6;
#endif
#if LLVM_VERSION_MAJOR < 9
Constant *
#else
FunctionCallee
#endif
c7 = M.getOrInsertFunction("__cmplog_rtn_hook_str", VoidTy, i8PtrTy,
i8PtrTy
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
Function *cmplogHookFnStr = cast<Function>(c7);
#else
FunctionCallee cmplogHookFnStr = c7;
#endif
GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map"); GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map");
if (!AFLCmplogPtr) { if (!AFLCmplogPtr) {
@ -214,12 +270,93 @@ bool CmpLogRoutines::hookRtns(Module &M) {
if (callInst->getCallingConv() != llvm::CallingConv::C) continue; if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
FunctionType *FT = Callee->getFunctionType(); FunctionType *FT = Callee->getFunctionType();
std::string FuncName = Callee->getName().str();
bool isPtrRtn = FT->getNumParams() >= 2 && bool isPtrRtn = FT->getNumParams() >= 2 &&
!FT->getReturnType()->isVoidTy() && !FT->getReturnType()->isVoidTy() &&
FT->getParamType(0) == FT->getParamType(1) && FT->getParamType(0) == FT->getParamType(1) &&
FT->getParamType(0)->isPointerTy(); FT->getParamType(0)->isPointerTy();
bool isPtrRtnN = FT->getNumParams() >= 3 &&
!FT->getReturnType()->isVoidTy() &&
FT->getParamType(0) == FT->getParamType(1) &&
FT->getParamType(0)->isPointerTy() &&
FT->getParamType(2)->isIntegerTy();
if (isPtrRtnN) {
auto intTyOp =
dyn_cast<IntegerType>(callInst->getArgOperand(2)->getType());
if (intTyOp) {
if (intTyOp->getBitWidth() != 32 &&
intTyOp->getBitWidth() != 64) {
isPtrRtnN = false;
}
}
}
bool isMemcmp =
(!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
!FuncName.compare("CRYPTO_memcmp") ||
!FuncName.compare("OPENSSL_memcmp") ||
!FuncName.compare("memcmp_const_time") ||
!FuncName.compare("memcmpct"));
isMemcmp &= FT->getNumParams() == 3 &&
FT->getReturnType()->isIntegerTy(32) &&
FT->getParamType(0)->isPointerTy() &&
FT->getParamType(1)->isPointerTy() &&
FT->getParamType(2)->isIntegerTy();
bool isStrcmp =
(!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
!FuncName.compare("xmlStrEqual") ||
!FuncName.compare("g_strcmp0") ||
!FuncName.compare("curl_strequal") ||
!FuncName.compare("strcsequal") ||
!FuncName.compare("strcasecmp") ||
!FuncName.compare("stricmp") ||
!FuncName.compare("ap_cstr_casecmp") ||
!FuncName.compare("OPENSSL_strcasecmp") ||
!FuncName.compare("xmlStrcasecmp") ||
!FuncName.compare("g_strcasecmp") ||
!FuncName.compare("g_ascii_strcasecmp") ||
!FuncName.compare("Curl_strcasecompare") ||
!FuncName.compare("Curl_safe_strcasecompare") ||
!FuncName.compare("cmsstrcasecmp") ||
!FuncName.compare("strstr") ||
!FuncName.compare("g_strstr_len") ||
!FuncName.compare("ap_strcasestr") ||
!FuncName.compare("xmlStrstr") ||
!FuncName.compare("xmlStrcasestr") ||
!FuncName.compare("g_str_has_prefix") ||
!FuncName.compare("g_str_has_suffix"));
isStrcmp &=
FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
FT->getParamType(0) == FT->getParamType(1) &&
FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
bool isStrncmp = (!FuncName.compare("strncmp") ||
!FuncName.compare("xmlStrncmp") ||
!FuncName.compare("curl_strnequal") ||
!FuncName.compare("strncasecmp") ||
!FuncName.compare("strnicmp") ||
!FuncName.compare("ap_cstr_casecmpn") ||
!FuncName.compare("OPENSSL_strncasecmp") ||
!FuncName.compare("xmlStrncasecmp") ||
!FuncName.compare("g_ascii_strncasecmp") ||
!FuncName.compare("Curl_strncasecompare") ||
!FuncName.compare("g_strncasecmp"));
isStrncmp &= FT->getNumParams() == 3 &&
FT->getReturnType()->isIntegerTy(32) &&
FT->getParamType(0) == FT->getParamType(1) &&
FT->getParamType(0) ==
IntegerType::getInt8PtrTy(M.getContext()) &&
FT->getParamType(2)->isIntegerTy();
bool isGccStdStringStdString = bool isGccStdStringStdString =
Callee->getName().find("__is_charIT_EE7__value") != Callee->getName().find("__is_charIT_EE7__value") !=
std::string::npos && std::string::npos &&
@ -267,13 +404,19 @@ bool CmpLogRoutines::hookRtns(Module &M) {
*/ */
if (isGccStdStringCString || isGccStdStringStdString || if (isGccStdStringCString || isGccStdStringStdString ||
isLlvmStdStringStdString || isLlvmStdStringCString) { isLlvmStdStringStdString || isLlvmStdStringCString || isMemcmp ||
isStrcmp || isStrncmp) {
isPtrRtn = false; isPtrRtnN = isPtrRtn = false;
} }
if (isPtrRtnN) { isPtrRtn = false; }
if (isPtrRtn) { calls.push_back(callInst); } if (isPtrRtn) { calls.push_back(callInst); }
if (isMemcmp || isPtrRtnN) { Memcmp.push_back(callInst); }
if (isStrcmp) { Strcmp.push_back(callInst); }
if (isStrncmp) { Strncmp.push_back(callInst); }
if (isGccStdStringStdString) { gccStdStd.push_back(callInst); } if (isGccStdStringStdString) { gccStdStd.push_back(callInst); }
if (isGccStdStringCString) { gccStdC.push_back(callInst); } if (isGccStdStringCString) { gccStdC.push_back(callInst); }
if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); } if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); }
@ -288,7 +431,8 @@ bool CmpLogRoutines::hookRtns(Module &M) {
} }
if (!calls.size() && !gccStdStd.size() && !gccStdC.size() && if (!calls.size() && !gccStdStd.size() && !gccStdC.size() &&
!llvmStdStd.size() && !llvmStdC.size()) !llvmStdStd.size() && !llvmStdC.size() && !Memcmp.size() &&
Strcmp.size() && Strncmp.size())
return false; return false;
/* /*
@ -323,6 +467,96 @@ bool CmpLogRoutines::hookRtns(Module &M) {
} }
for (auto &callInst : Memcmp) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1),
*v3P = callInst->getArgOperand(2);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);
LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);
IRBuilder<> IRB(ThenTerm);
std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
Value * v3Pbitcast = IRB.CreateBitCast(
v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits()));
Value *v3Pcasted =
IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false);
args.push_back(v1Pcasted);
args.push_back(v2Pcasted);
args.push_back(v3Pcasted);
IRB.CreateCall(cmplogHookFnN, args);
// errs() << callInst->getCalledFunction()->getName() << "\n";
}
for (auto &callInst : Strcmp) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);
LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);
IRBuilder<> IRB(ThenTerm);
std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
args.push_back(v1Pcasted);
args.push_back(v2Pcasted);
IRB.CreateCall(cmplogHookFnStr, args);
// errs() << callInst->getCalledFunction()->getName() << "\n";
}
for (auto &callInst : Strncmp) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1),
*v3P = callInst->getArgOperand(2);
IRBuilder<> IRB2(callInst->getParent());
IRB2.SetInsertPoint(callInst);
LoadInst *CmpPtr = IRB2.CreateLoad(AFLCmplogPtr);
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);
IRBuilder<> IRB(ThenTerm);
std::vector<Value *> args;
Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
Value * v3Pbitcast = IRB.CreateBitCast(
v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits()));
Value *v3Pcasted =
IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false);
args.push_back(v1Pcasted);
args.push_back(v2Pcasted);
args.push_back(v3Pcasted);
IRB.CreateCall(cmplogHookFnStrN, args);
// errs() << callInst->getCalledFunction()->getName() << "\n";
}
for (auto &callInst : gccStdStd) { for (auto &callInst : gccStdStd) {
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);

View File

@ -1 +1 @@
71ed0d206f 8809a2b2ebf089d3427dd8f6a0044bcc2e13b389

View File

@ -342,6 +342,16 @@ static void report_error_and_exit(int error) {
"the fuzzing target reports that the mmap() call to the shared " "the fuzzing target reports that the mmap() call to the shared "
"memory failed."); "memory failed.");
break; break;
case FS_ERROR_OLD_CMPLOG:
FATAL(
"the -c cmplog target was instrumented with an too old afl++ "
"version, you need to recompile it.");
break;
case FS_ERROR_OLD_CMPLOG_QEMU:
FATAL(
"The AFL++ QEMU/FRIDA loaders are from an older version, for -c you "
"need to recompile it.\n");
break;
default: default:
FATAL("unknown error code %d from fuzzing target!", error); FATAL("unknown error code %d from fuzzing target!", error);
@ -663,6 +673,20 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND) if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
status = (status & 0xf0ffffff); status = (status & 0xf0ffffff);
if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
if (fsrv->qemu_mode || fsrv->frida_mode) {
report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
} else {
report_error_and_exit(FS_ERROR_OLD_CMPLOG);
}
}
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
fsrv->snapshot = 1; fsrv->snapshot = 1;

View File

@ -448,11 +448,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
ACTF( ACTF(
"Fuzzing test case #%u (%u total, %llu uniq crashes found, " "Fuzzing test case #%u (%u total, %llu uniq crashes found, "
"perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u)...", "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u, ascii=%u)...",
afl->current_entry, afl->queued_paths, afl->unique_crashes, afl->current_entry, afl->queued_paths, afl->unique_crashes,
afl->queue_cur->perf_score, afl->queue_cur->exec_us, afl->queue_cur->perf_score, afl->queue_cur->exec_us,
likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0, likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
afl->queue_cur->bitmap_size); afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii);
fflush(stdout); fflush(stdout);
} }
@ -2003,11 +2003,16 @@ havoc_stage:
where we take the input file and make random stacked tweaks. */ where we take the input file and make random stacked tweaks. */
#define MAX_HAVOC_ENTRY 59 /* 55 to 60 */ #define MAX_HAVOC_ENTRY 59 /* 55 to 60 */
#define MUTATE_ASCII_DICT 64
u32 r_max, r; u32 r_max, r;
r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) + r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) +
(afl->a_extras_cnt ? 4 : 0); (afl->a_extras_cnt
? (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)
? MUTATE_ASCII_DICT
: 4)
: 0);
if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
@ -2592,7 +2597,15 @@ havoc_stage:
if (afl->a_extras_cnt) { if (afl->a_extras_cnt) {
if (r < 2) { u32 r_cmp = 2;
if (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)) {
r_cmp = MUTATE_ASCII_DICT >> 1;
}
if (r < r_cmp) {
/* Use the dictionary. */ /* Use the dictionary. */
@ -2612,7 +2625,7 @@ havoc_stage:
break; break;
} else if (r < 4) { } else if (r < (r_cmp << 1)) {
u32 use_extra = rand_below(afl, afl->a_extras_cnt); u32 use_extra = rand_below(afl, afl->a_extras_cnt);
u32 extra_len = afl->a_extras[use_extra].len; u32 extra_len = afl->a_extras[use_extra].len;
@ -2641,7 +2654,7 @@ havoc_stage:
} else { } else {
r -= 4; r -= (r_cmp << 1);
} }

View File

@ -315,7 +315,96 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
} }
/* check if ascii or UTF-8 */ /* check if pointer is ascii or UTF-8 */
u8 check_if_text_buf(u8 *buf, u32 len) {
u32 offset = 0, ascii = 0, utf8 = 0;
while (offset < len) {
// ASCII: <= 0x7F to allow ASCII control characters
if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A ||
buf[offset + 0] == 0x0D ||
(0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) {
offset++;
utf8++;
ascii++;
continue;
}
if (isascii((int)buf[offset]) || isprint((int)buf[offset])) {
ascii++;
// we continue though as it can also be a valid utf8
}
// non-overlong 2-byte
if (len - offset > 1 &&
((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) &&
(0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) {
offset += 2;
utf8++;
continue;
}
// excluding overlongs
if ((len - offset > 2) &&
((buf[offset + 0] == 0xE0 &&
(0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
(0x80 <= buf[offset + 2] &&
buf[offset + 2] <= 0xBF)) || // straight 3-byte
(((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) ||
buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) &&
(0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
(0x80 <= buf[offset + 2] &&
buf[offset + 2] <= 0xBF)) || // excluding surrogates
(buf[offset + 0] == 0xED &&
(0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) &&
(0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF)))) {
offset += 3;
utf8++;
continue;
}
// planes 1-3
if ((len - offset > 3) &&
((buf[offset + 0] == 0xF0 &&
(0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
(0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
(0x80 <= buf[offset + 3] &&
buf[offset + 3] <= 0xBF)) || // planes 4-15
((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) &&
(0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
(0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
(0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16
(buf[offset + 0] == 0xF4 &&
(0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) &&
(0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
(0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)))) {
offset += 4;
utf8++;
continue;
}
offset++;
}
return (utf8 > ascii ? utf8 : ascii);
}
/* check if queue entry is ascii or UTF-8 */
static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) { static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) {

View File

@ -45,6 +45,23 @@ enum {
}; };
// add to dictionary enum
// DEFAULT = 1, notTXT = 2, FOUND = 4, notSAME = 8
enum {
DICT_ADD_NEVER = 0,
DICT_ADD_NOTFOUND_SAME_TXT = 1,
DICT_ADD_NOTFOUND_SAME = 3,
DICT_ADD_FOUND_SAME_TXT = 5,
DICT_ADD_FOUND_SAME = 7,
DICT_ADD_NOTFOUND_TXT = 9,
DICT_ADD_NOTFOUND = 11,
DICT_ADD_FOUND_TXT = 13,
DICT_ADD_FOUND = 15,
DICT_ADD_ANY = DICT_ADD_FOUND
};
// CMPLOG LVL // CMPLOG LVL
enum { enum {
@ -54,6 +71,8 @@ enum {
}; };
#define DICT_ADD_STRATEGY DICT_ADD_FOUND_SAME
struct range { struct range {
u32 start; u32 start;
@ -64,6 +83,10 @@ struct range {
}; };
static u32 hshape;
static u64 screen_update;
static u64 last_update;
static struct range *add_range(struct range *ranges, u32 start, u32 end) { static struct range *add_range(struct range *ranges, u32 start, u32 end) {
struct range *r = ck_alloc_nozero(sizeof(struct range)); struct range *r = ck_alloc_nozero(sizeof(struct range));
@ -252,7 +275,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
u64 start_time = get_cur_time(); u64 start_time = get_cur_time();
#endif #endif
u32 screen_update;
u64 orig_hit_cnt, new_hit_cnt, exec_cksum; u64 orig_hit_cnt, new_hit_cnt, exec_cksum;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes; orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
@ -261,24 +283,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
afl->stage_max = (len << 1); afl->stage_max = (len << 1);
afl->stage_cur = 0; afl->stage_cur = 0;
if (likely(afl->queue_cur->exec_us)) {
if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
screen_update = 100000 / afl->queue_cur->exec_us;
} else {
screen_update = 1;
}
} else {
screen_update = 100000;
}
// in colorization we do not classify counts, hence we have to calculate // in colorization we do not classify counts, hence we have to calculate
// the original checksum. // the original checksum.
if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) { if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) {
@ -348,7 +352,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
} }
if (++afl->stage_cur % screen_update) { show_stats(afl); }; if (++afl->stage_cur % screen_update == 0) { show_stats(afl); };
} }
@ -440,10 +444,10 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
fprintf( fprintf(
f, f,
"Colorization: fname=%s len=%u ms=%llu result=%u execs=%u found=%llu " "Colorization: fname=%s len=%u ms=%llu result=%u execs=%u found=%llu "
"taint=%u\n", "taint=%u ascii=%u auto_extra_before=%u\n",
afl->queue_cur->fname, len, get_cur_time() - start_time, afl->queue_cur->fname, len, get_cur_time() - start_time,
afl->queue_cur->colorized, afl->stage_cur, new_hit_cnt - orig_hit_cnt, afl->queue_cur->colorized, afl->stage_cur, new_hit_cnt - orig_hit_cnt,
positions); positions, afl->queue_cur->is_ascii ? 1 : 0, afl->a_extras_cnt);
#ifndef _DEBUG #ifndef _DEBUG
if (afl->not_on_tty) { fclose(f); } if (afl->not_on_tty) { fclose(f); }
@ -759,11 +763,18 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 its_len = MIN(len - idx, taint_len); u32 its_len = MIN(len - idx, taint_len);
if (afl->fsrv.total_execs - last_update > screen_update) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
}
// fprintf(stderr, // fprintf(stderr,
// "Encode: %llx->%llx into %llx(<-%llx) at idx=%u " // "Encode: %llx->%llx into %llx(<-%llx) at idx=%u "
// "taint_len=%u shape=%u attr=%u\n", // "taint_len=%u shape=%u attr=%u\n",
// o_pattern, pattern, repl, changed_val, idx, taint_len, // o_pattern, pattern, repl, changed_val, idx, taint_len,
// h->shape + 1, attr); // hshape, attr);
//#ifdef CMPLOG_SOLVE_TRANSFORM //#ifdef CMPLOG_SOLVE_TRANSFORM
// 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
@ -845,7 +856,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 b_val, o_b_val, mask; u64 b_val, o_b_val, mask;
u8 bytes; u8 bytes;
switch (SHAPE_BYTES(h->shape)) { switch (hshape) {
case 0: case 0:
case 1: case 1:
@ -924,7 +935,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
s64 diff = pattern - b_val; s64 diff = pattern - b_val;
s64 o_diff = o_pattern - o_b_val; s64 o_diff = o_pattern - o_b_val;
/* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx, /* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
h->shape + 1, o_pattern, o_b_val, o_diff); hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern, fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
b_val, diff); */ b_val, diff); */
if (diff == o_diff && diff) { if (diff == o_diff && diff) {
@ -953,7 +964,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
s64 o_diff = o_pattern ^ o_b_val; s64 o_diff = o_pattern ^ o_b_val;
/* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n", /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff); idx, hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr, fprintf(stderr,
"DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff); "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/ */
@ -1002,7 +1013,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
/* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n", /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff); idx, hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr, fprintf(stderr,
"DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff); "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/ */
@ -1051,7 +1062,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
/* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n", /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff); idx, hshape, o_pattern, o_b_val, o_diff);
fprintf(stderr, fprintf(stderr,
"DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff); "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/ */
@ -1089,7 +1100,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if ((lvl & LVL1) || attr >= IS_FP_MOD) { if ((lvl & LVL1) || attr >= IS_FP_MOD) {
if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) { if (hshape >= 8 && *status != 1) {
// if (its_len >= 8) // if (its_len >= 8)
// fprintf(stderr, // fprintf(stderr,
@ -1132,7 +1143,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
if (SHAPE_BYTES(h->shape) >= 4 && *status != 1) { if (hshape >= 4 && *status != 1) {
// if (its_len >= 4 && (attr <= 1 || attr >= 8)) // if (its_len >= 4 && (attr <= 1 || attr >= 8))
// fprintf(stderr, // fprintf(stderr,
@ -1173,7 +1184,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
if (SHAPE_BYTES(h->shape) >= 2 && *status != 1) { if (hshape >= 2 && *status != 1) {
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) ||
@ -1244,11 +1255,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { if (!(attr & (IS_GREATER | IS_LESSER)) || hshape < 4) { return 0; }
return 0;
}
// transform >= to < and <= to > // transform >= to < and <= to >
if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) { if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) {
@ -1272,7 +1279,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (attr & IS_GREATER) { if (attr & IS_GREATER) {
if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) { if (hshape == 4 && its_len >= 4) {
float *f = (float *)&repl; float *f = (float *)&repl;
float g = *f; float g = *f;
@ -1280,7 +1287,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 *r = (u32 *)&g; u32 *r = (u32 *)&g;
repl_new = (u32)*r; repl_new = (u32)*r;
} else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) { } else if (hshape == 8 && its_len >= 8) {
double *f = (double *)&repl; double *f = (double *)&repl;
double g = *f; double g = *f;
@ -1307,7 +1314,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} else { } else {
if (SHAPE_BYTES(h->shape) == 4) { if (hshape == 4) {
float *f = (float *)&repl; float *f = (float *)&repl;
float g = *f; float g = *f;
@ -1315,7 +1322,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 *r = (u32 *)&g; u32 *r = (u32 *)&g;
repl_new = (u32)*r; repl_new = (u32)*r;
} else if (SHAPE_BYTES(h->shape) == 8) { } else if (hshape == 8) {
double *f = (double *)&repl; double *f = (double *)&repl;
double g = *f; double g = *f;
@ -1342,7 +1349,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} }
// transform double to float, llvm likes to do that internally ... // transform double to float, llvm likes to do that internally ...
if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) { if (hshape == 8 && its_len >= 4) {
double *f = (double *)&repl; double *f = (double *)&repl;
float g = (float)*f; float g = (float)*f;
@ -1353,7 +1360,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
memcpy(((char *)&repl_new) + 4, (char *)&g, 4); memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
#endif #endif
changed_val = repl_new; changed_val = repl_new;
h->shape = 3; // modify shape hshape = 4; // modify shape
// fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new); // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new);
@ -1361,12 +1368,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
h->shape = 7; // recover shape hshape = 8; // recover shape
return 1; return 1;
} }
h->shape = 7; // recover shape hshape = 8; // recover shape
} }
@ -1421,6 +1428,13 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 do_reverse, u8 lvl, u8 *status) { u32 len, u8 do_reverse, u8 lvl, u8 *status) {
if (afl->fsrv.total_execs - last_update > screen_update) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
}
u8 *ptr = (u8 *)&buf[idx]; u8 *ptr = (u8 *)&buf[idx];
u8 *o_ptr = (u8 *)&orig_buf[idx]; u8 *o_ptr = (u8 *)&orig_buf[idx];
u8 *p = (u8 *)&pattern; u8 *p = (u8 *)&pattern;
@ -1428,52 +1442,51 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u8 *r = (u8 *)&repl; u8 *r = (u8 *)&repl;
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;
#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 - hshape;
#endif #endif
if (its_len >= shape) { if (its_len >= hshape) {
#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, hshape, len, idx, attr, off, do_reverse);
u32 i; u32 i;
u8 *o_r = (u8 *)&changed_val; u8 *o_r = (u8 *)&changed_val;
for (i = 0; i < shape; i++) for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", ptr[i]); fprintf(stderr, "%02x", ptr[i]);
fprintf(stderr, "=="); fprintf(stderr, "==");
for (i = 0; i < shape; i++) for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", p[off + i]); fprintf(stderr, "%02x", p[off + i]);
fprintf(stderr, " "); fprintf(stderr, " ");
for (i = 0; i < shape; i++) for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", o_ptr[i]); fprintf(stderr, "%02x", o_ptr[i]);
fprintf(stderr, "=="); fprintf(stderr, "==");
for (i = 0; i < shape; i++) for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", o_p[off + i]); fprintf(stderr, "%02x", o_p[off + i]);
fprintf(stderr, " <= "); fprintf(stderr, " <= ");
for (i = 0; i < shape; i++) for (i = 0; i < hshape; i++)
fprintf(stderr, "%02x", r[off + i]); fprintf(stderr, "%02x", r[off + i]);
fprintf(stderr, "<-"); fprintf(stderr, "<-");
for (i = 0; i < shape; i++) for (i = 0; i < hshape; 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, hshape) && !memcmp(o_ptr, o_p + off, hshape)) {
memcpy(backup, ptr, shape); memcpy(backup, ptr, hshape);
memcpy(ptr, r + off, shape); memcpy(ptr, r + off, hshape);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE #ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, r, shape); } if (*status == 1) { memcpy(cbuf + idx, r, hshape); }
#endif #endif
memcpy(ptr, backup, shape); memcpy(ptr, backup, hshape);
#ifdef _DEBUG #ifdef _DEBUG
fprintf(stderr, "Status=%u\n", *status); fprintf(stderr, "Status=%u\n", *status);
@ -1485,10 +1498,10 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
if (do_reverse && *status != 1) { if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encodingN( if (unlikely(cmp_extend_encodingN(
afl, h, SWAPN(pattern, (shape << 3)), SWAPN(repl, (shape << 3)), afl, h, SWAPN(pattern, (hshape << 3)), SWAPN(repl, (hshape << 3)),
SWAPN(o_pattern, (shape << 3)), SWAPN(changed_val, (shape << 3)), SWAPN(o_pattern, (hshape << 3)),
attr, idx, taint_len, orig_buf, buf, cbuf, len, 0, lvl, SWAPN(changed_val, (hshape << 3)), attr, idx, taint_len, orig_buf,
status))) { buf, cbuf, len, 0, lvl, status))) {
return 1; return 1;
@ -1615,6 +1628,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u8 s_v0_inc = 1, s_v1_inc = 1; u8 s_v0_inc = 1, s_v1_inc = 1;
u8 s_v0_dec = 1, s_v1_dec = 1; u8 s_v0_dec = 1, s_v1_dec = 1;
hshape = SHAPE_BYTES(h->shape);
if (h->hits > CMP_MAP_H) { if (h->hits > CMP_MAP_H) {
loggeds = CMP_MAP_H; loggeds = CMP_MAP_H;
@ -1626,7 +1641,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
#ifdef WORD_SIZE_64 #ifdef WORD_SIZE_64
switch (SHAPE_BYTES(h->shape)) { switch (hshape) {
case 1: case 1:
case 2: case 2:
@ -1679,8 +1694,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#ifdef _DEBUG #ifdef _DEBUG
fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n", fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
SHAPE_BYTES(h->shape));
#endif #endif
t = taint; t = taint;
@ -1830,27 +1844,41 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
"END: %llx->%llx vs %llx->%llx attr=%u i=%u found=%u " "END: %llx->%llx vs %llx->%llx attr=%u i=%u found=%u "
"isN=%u size=%u\n", "isN=%u size=%u\n",
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, i, found_one, orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, i, found_one,
is_n, SHAPE_BYTES(h->shape)); is_n, hshape);
#endif #endif
// If failed, add to dictionary // we only learn 16 bit +
if (!found_one) { if (hshape > 1) {
if (afl->pass_stats[key].total == 0) { if (!found_one || afl->queue_cur->is_ascii) {
#ifdef WORD_SIZE_64 #ifdef WORD_SIZE_64
if (unlikely(is_n)) { if (unlikely(is_n)) {
try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape)); if (!found_one ||
try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape)); check_if_text_buf((u8 *)&s128_v0, SHAPE_BYTES(h->shape)) ==
SHAPE_BYTES(h->shape))
try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
if (!found_one ||
check_if_text_buf((u8 *)&s128_v1, SHAPE_BYTES(h->shape)) ==
SHAPE_BYTES(h->shape))
try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
} else } else
#endif #endif
{ {
try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape)); if (!memcmp((u8 *)&o->v0, (u8 *)&orig_o->v0, SHAPE_BYTES(h->shape)) &&
try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape)); (!found_one ||
check_if_text_buf((u8 *)&o->v0, SHAPE_BYTES(h->shape)) ==
SHAPE_BYTES(h->shape)))
try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
if (!memcmp((u8 *)&o->v1, (u8 *)&orig_o->v1, SHAPE_BYTES(h->shape)) &&
(!found_one ||
check_if_text_buf((u8 *)&o->v1, SHAPE_BYTES(h->shape)) ==
SHAPE_BYTES(h->shape)))
try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
} }
@ -1882,8 +1910,9 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
u8 *o_pattern, u8 *changed_val, u8 plen, u32 idx, struct cmpfn_operands *o,
struct cmpfn_operands *orig_o, u32 idx,
u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 lvl, u8 *status) { u32 len, u8 lvl, u8 *status) {
@ -1894,9 +1923,60 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
// (void)(changed_val); // (void)(changed_val);
//#endif //#endif
if (afl->fsrv.total_execs - last_update > screen_update) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
}
u8 *pattern, *repl, *o_pattern, *changed_val;
u8 l0, l1, ol0, ol1;
if (entry == 0) {
pattern = o->v0;
repl = o->v1;
o_pattern = orig_o->v0;
changed_val = orig_o->v1;
l0 = o->v0_len;
ol0 = orig_o->v0_len;
l1 = o->v1_len;
ol1 = orig_o->v1_len;
} else {
pattern = o->v1;
repl = o->v0;
o_pattern = orig_o->v1;
changed_val = orig_o->v0;
l0 = o->v1_len;
ol0 = orig_o->v1_len;
l1 = o->v0_len;
ol1 = orig_o->v0_len;
}
if (l0 >= 0x80 || ol0 >= 0x80) {
l0 -= 0x80;
l1 -= 0x80;
ol0 -= 0x80;
ol1 -= 0x80;
}
if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
ol0 > 31 || ol1 > 31) {
l0 = l1 = ol0 = ol1 = hshape;
}
u8 lmax = MAX(l0, ol0);
u8 save[40]; u8 save[40];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j; u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
u32 its_len = MIN((u32)plen, len - idx); u32 its_len = MIN(MIN(lmax, hshape), len - idx);
its_len = MIN(its_len, taint_len); its_len = MIN(its_len, taint_len);
u32 saved_its_len = its_len; u32 saved_its_len = its_len;
@ -1912,7 +1992,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
(void)(j); (void)(j);
#ifdef _DEBUG #ifdef _DEBUG
fprintf(stderr, "RTN T idx=%u lvl=%02x ", idx, lvl); fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl,
o->v0_len >= 0x80 ? 1 : 0, hshape, l0);
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_buf[idx + j]); fprintf(stderr, "%02x", orig_buf[idx + j]);
fprintf(stderr, " -> "); fprintf(stderr, " -> ");
@ -1972,10 +2053,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
} }
//#ifdef CMPLOG_SOLVE_TRANSFORM
if (*status == 1) return 0; if (*status == 1) return 0;
// transform solving
if (afl->cmplog_enable_transform && (lvl & LVL3)) { if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0; u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
@ -2322,6 +2403,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 i, j, idx, have_taint = 1, taint_len, loggeds; u32 i, j, idx, have_taint = 1, taint_len, loggeds;
u8 status = 0, found_one = 0; u8 status = 0, found_one = 0;
hshape = SHAPE_BYTES(h->shape);
if (h->hits > CMP_MAP_RTN_H) { if (h->hits > CMP_MAP_RTN_H) {
loggeds = CMP_MAP_RTN_H; loggeds = CMP_MAP_RTN_H;
@ -2353,18 +2436,22 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
/* /*
struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
h->id, h->shape, h->attribute); hshape, h->attribute);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]); for (j = 0; j < 8; j++)
fprintf(stderr, " v1="); fprintf(stderr, "%02x", o->v0[j]);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]); fprintf(stderr, " v1=");
fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", for (j = 0; j < 8; j++)
hh->hits, hh->id, hh->shape, hh->attribute); fprintf(stderr, "%02x", o->v1[j]);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]); fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits,
fprintf(stderr, " o1="); hh->id, hshape, hh->attribute);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]); for (j = 0; j < 8; j++)
fprintf(stderr, "\n"); fprintf(stderr, "%02x", orig_o->v0[j]);
fprintf(stderr, " o1=");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_o->v1[j]);
fprintf(stderr, "\n");
*/ */
t = taint; t = taint;
@ -2400,25 +2487,24 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#ifdef _DEBUG #ifdef _DEBUG
int w; int w;
fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx, fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx, hshape);
SHAPE_BYTES(h->shape)); for (w = 0; w < hshape; ++w)
for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
fprintf(stderr, "%02x", orig_o->v0[w]); fprintf(stderr, "%02x", orig_o->v0[w]);
fprintf(stderr, " v0="); fprintf(stderr, " v0=");
for (w = 0; w < SHAPE_BYTES(h->shape); ++w) for (w = 0; w < hshape; ++w)
fprintf(stderr, "%02x", o->v0[w]); fprintf(stderr, "%02x", o->v0[w]);
fprintf(stderr, " o1="); fprintf(stderr, " o1=");
for (w = 0; w < SHAPE_BYTES(h->shape); ++w) for (w = 0; w < hshape; ++w)
fprintf(stderr, "%02x", orig_o->v1[w]); fprintf(stderr, "%02x", orig_o->v1[w]);
fprintf(stderr, " v1="); fprintf(stderr, " v1=");
for (w = 0; w < SHAPE_BYTES(h->shape); ++w) for (w = 0; w < hshape; ++w)
fprintf(stderr, "%02x", o->v1[w]); fprintf(stderr, "%02x", o->v1[w]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
if (unlikely(rtn_extend_encoding( if (unlikely(rtn_extend_encoding(afl, 0, o, orig_o, idx, taint_len,
afl, o->v0, o->v1, orig_o->v0, orig_o->v1, SHAPE_BYTES(h->shape), orig_buf, buf, cbuf, len, lvl,
idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) { &status))) {
return 1; return 1;
@ -2433,9 +2519,9 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
status = 0; status = 0;
if (unlikely(rtn_extend_encoding( if (unlikely(rtn_extend_encoding(afl, 1, o, orig_o, idx, taint_len,
afl, o->v1, o->v0, orig_o->v1, orig_o->v0, SHAPE_BYTES(h->shape), orig_buf, buf, cbuf, len, lvl,
idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) { &status))) {
return 1; return 1;
@ -2450,16 +2536,42 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
} }
// If failed, add to dictionary // if (unlikely(!afl->pass_stats[key].total)) {
if (!found_one && (lvl & LVL1)) {
if (unlikely(!afl->pass_stats[key].total)) { if ((!found_one && (lvl & LVL1)) || afl->queue_cur->is_ascii) {
maybe_add_auto(afl, o->v0, SHAPE_BYTES(h->shape)); // if (unlikely(!afl->pass_stats[key].total)) {
maybe_add_auto(afl, o->v1, SHAPE_BYTES(h->shape));
u32 shape_len = SHAPE_BYTES(h->shape);
u32 v0_len = shape_len, v1_len = shape_len;
if (afl->queue_cur->is_ascii ||
check_if_text_buf((u8 *)&o->v0, shape_len) == shape_len) {
if (strlen(o->v0)) v0_len = strlen(o->v0);
} }
if (afl->queue_cur->is_ascii ||
check_if_text_buf((u8 *)&o->v1, shape_len) == shape_len) {
if (strlen(o->v1)) v1_len = strlen(o->v1);
}
// fprintf(stderr, "SHOULD: found:%u ascii:%u text?%u:%u %u:%s %u:%s \n",
// found_one, afl->queue_cur->is_ascii, check_if_text_buf((u8 *)&o->v0,
// shape_len), check_if_text_buf((u8 *)&o->v1, shape_len), v0_len,
// o->v0, v1_len, o->v1);
if (!memcmp(o->v0, orig_o->v0, v0_len) ||
(!found_one || check_if_text_buf((u8 *)&o->v0, v0_len) == v0_len))
maybe_add_auto(afl, o->v0, v0_len);
if (!memcmp(o->v1, orig_o->v1, v1_len) ||
(!found_one || check_if_text_buf((u8 *)&o->v1, v1_len) == v1_len))
maybe_add_auto(afl, o->v1, v1_len);
//}
} }
rtn_fuzz_next_iter: rtn_fuzz_next_iter:
@ -2492,6 +2604,23 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} }
struct tainted *taint = NULL; struct tainted *taint = NULL;
if (likely(afl->queue_cur->exec_us)) {
if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
screen_update = 100000 / afl->queue_cur->exec_us;
} else {
screen_update = 1;
}
} else {
screen_update = 100000;
}
if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) { if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
@ -2592,8 +2721,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u64 orig_hit_cnt, new_hit_cnt; u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->fsrv.total_execs; u64 orig_execs = afl->fsrv.total_execs;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes; orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
u64 screen_update = 100000 / afl->queue_cur->exec_us,
execs = afl->fsrv.total_execs;
afl->stage_name = "input-to-state"; afl->stage_name = "input-to-state";
afl->stage_short = "its"; afl->stage_short = "its";
@ -2630,11 +2757,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) { if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
// fprintf(stderr, "INS %u\n", k);
afl->stage_max += afl->stage_max +=
MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_H); MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_H);
} else { } else {
// fprintf(stderr, "RTN %u\n", k);
afl->stage_max += afl->stage_max +=
MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_RTN_H); MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_RTN_H);
@ -2673,13 +2802,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} }
if (afl->fsrv.total_execs - execs > screen_update) {
execs = afl->fsrv.total_execs;
show_stats(afl);
}
} }
r = 0; r = 0;
@ -2795,9 +2917,10 @@ exit_its:
if (f) { if (f) {
fprintf(f, fprintf(f,
"Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u\n", "Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u "
"auto_extra_after=%u\n",
afl->queue_cur->fname, len, get_cur_time() - start_time, r, afl->queue_cur->fname, len, get_cur_time() - start_time, r,
new_hit_cnt - orig_hit_cnt, cmp_locations); new_hit_cnt - orig_hit_cnt, cmp_locations, afl->a_extras_cnt);
#ifndef _DEBUG #ifndef _DEBUG
if (afl->not_on_tty) { fclose(f); } if (afl->not_on_tty) { fclose(f); }

View File

@ -278,6 +278,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"total_edges : %u\n" "total_edges : %u\n"
"var_byte_count : %u\n" "var_byte_count : %u\n"
"havoc_expansion : %u\n" "havoc_expansion : %u\n"
"auto_dict_entries : %u\n"
"testcache_size : %llu\n" "testcache_size : %llu\n"
"testcache_count : %u\n" "testcache_count : %u\n"
"testcache_evict : %u\n" "testcache_evict : %u\n"
@ -316,7 +317,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
-1, -1,
#endif #endif
t_bytes, afl->fsrv.real_map_size, afl->var_byte_count, t_bytes, afl->fsrv.real_map_size, afl->var_byte_count,
afl->expand_havoc, afl->q_testcase_cache_size, afl->expand_havoc, afl->a_extras_cnt, afl->q_testcase_cache_size,
afl->q_testcase_cache_count, afl->q_testcase_evictions, afl->q_testcase_cache_count, afl->q_testcase_evictions,
afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
afl->fsrv.qemu_mode ? "qemu " : "", afl->fsrv.qemu_mode ? "qemu " : "",

View File

@ -2235,13 +2235,12 @@ int main(int argc, char **argv_orig, char **envp) {
} }
write_bitmap(afl);
save_auto(afl);
stop_fuzzing: stop_fuzzing:
afl->force_ui_update = 1; // ensure the screen is reprinted afl->force_ui_update = 1; // ensure the screen is reprinted
show_stats(afl); // print the screen one last time show_stats(afl); // print the screen one last time
write_bitmap(afl);
save_auto(afl);
SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST,
afl->stop_soon == 2 ? "programmatically" : "by user"); afl->stop_soon == 2 ? "programmatically" : "by user");
@ -2270,6 +2269,20 @@ stop_fuzzing:
} }
if (afl->not_on_tty) {
u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
u8 time_tmp[64];
u_stringify_time_diff(time_tmp, get_cur_time(), afl->start_time);
ACTF(
"Statistics: %u new paths found, %.02f%% coverage achieved, %llu "
"crashes found, %llu timeouts found, total runtime %s",
afl->queued_discovered,
((double)t_bytes * 100) / afl->fsrv.real_map_size, afl->unique_crashes,
afl->unique_hangs, time_tmp);
}
#ifdef PROFILING #ifdef PROFILING
SAYF(cYEL "[!] " cRST SAYF(cYEL "[!] " cRST
"Profiling information: %llu ms total work, %llu ns/run\n", "Profiling information: %llu ms total work, %llu ns/run\n",

View File

@ -90,7 +90,8 @@ inline u32 hash32(u8 *key, u32 len, u32 seed) {
#endif #endif
return (u32)XXH64(key, len, seed); (void)seed;
return (u32)XXH3_64bits(key, len);
} }
@ -102,7 +103,8 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
#endif #endif
return XXH64(key, len, seed); (void)seed;
return XXH3_64bits(key, len);
} }

View File

@ -1,15 +1,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
int main(int argc, char *argv[]) {
char buf[1024]; int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t i) {
ssize_t i; if (i < 24) return 0;
if ((i = read(0, buf, sizeof(buf) - 1)) < 24) return 0;
buf[i] = 0;
if (buf[0] != 'A') return 0; if (buf[0] != 'A') return 0;
if (buf[1] != 'B') return 0; if (buf[1] != 'B') return 0;
if (buf[2] != 'C') return 0; if (buf[2] != 'C') return 0;
@ -18,6 +16,17 @@ int main(int argc, char *argv[]) {
if (strncmp(buf + 12, "IJKL", 4) == 0 && strcmp(buf + 16, "DEADBEEF") == 0) if (strncmp(buf + 12, "IJKL", 4) == 0 && strcmp(buf + 16, "DEADBEEF") == 0)
abort(); abort();
return 0; return 0;
} }
#ifdef __AFL_COMPILER
int main(int argc, char *argv[]) {
unsigned char buf[1024];
ssize_t i;
while(__AFL_LOOP(1000)) {
i = read(0, (char*)buf, sizeof(buf) - 1);
if (i > 0) buf[i] = 0;
LLVMFuzzerTestOneInput(buf, i);
}
return 0;
}
#endif