This commit is contained in:
hexcoder-
2021-02-18 19:40:22 +01:00
3 changed files with 551 additions and 677 deletions

View File

@ -0,0 +1,3 @@
#ifndef LOG_E
#define LOG_E LOG_F
#endif

View File

@ -208,6 +208,7 @@ typedef struct {
const char* crashDir; const char* crashDir;
const char* covDirNew; const char* covDirNew;
bool saveUnique; bool saveUnique;
bool saveSmaller;
size_t dynfileqMaxSz; size_t dynfileqMaxSz;
size_t dynfileqCnt; size_t dynfileqCnt;
dynfile_t* dynfileqCurrent; dynfile_t* dynfileqCurrent;
@ -279,9 +280,9 @@ typedef struct {
cmpfeedback_t* cmpFeedbackMap; cmpfeedback_t* cmpFeedbackMap;
int cmpFeedbackFd; int cmpFeedbackFd;
bool cmpFeedback; bool cmpFeedback;
const char* blacklistFile; const char* blocklistFile;
uint64_t* blacklist; uint64_t* blocklist;
size_t blacklistCnt; size_t blocklistCnt;
bool skipFeedbackOnTimeout; bool skipFeedbackOnTimeout;
uint64_t maxCov[4]; uint64_t maxCov[4];
dynFileMethod_t dynFileMethod; dynFileMethod_t dynFileMethod;

View File

@ -39,74 +39,58 @@
#include "libhfcommon/log.h" #include "libhfcommon/log.h"
#include "libhfcommon/util.h" #include "libhfcommon/util.h"
static inline size_t mangle_LenLeft(run_t *run, size_t off) { static inline size_t mangle_LenLeft(run_t* run, size_t off) {
if (off >= run->dynfile->size) { if (off >= run->dynfile->size) {
LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size); LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
} }
return (run->dynfile->size - off - 1); return (run->dynfile->size - off - 1);
} }
/* Get a random value <1:max>, but prefer smaller ones - up to 4KiB */ /*
* Get a random value <1:max>, but prefer smaller ones
* Based on an idea by https://twitter.com/gamozolabs
*/
static inline size_t mangle_getLen(size_t max) { static inline size_t mangle_getLen(size_t max) {
if (max > _HF_INPUT_MAX_SIZE) { if (max > _HF_INPUT_MAX_SIZE) {
LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, (size_t)_HF_INPUT_MAX_SIZE);
LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, }
(size_t)_HF_INPUT_MAX_SIZE); if (max == 0) {
LOG_F("max == 0");
}
if (max == 1) {
return 1;
} }
if (max == 0) { LOG_F("max == 0"); }
if (max == 1) { return 1; }
/* Give 50% chance the the uniform distribution */ /* Give 50% chance the the uniform distribution */
switch (util_rndGet(0, 9)) { if (util_rnd64() & 1) {
return (size_t)util_rndGet(1, max);
case 0:
return (size_t)util_rndGet(1, HF_MIN(16, max));
case 1:
return (size_t)util_rndGet(1, HF_MIN(64, max));
case 2:
return (size_t)util_rndGet(1, HF_MIN(256, max));
case 3:
return (size_t)util_rndGet(1, HF_MIN(1024, max));
case 4:
return (size_t)util_rndGet(1, HF_MIN(4096, max));
default:
break;
} }
return (size_t)util_rndGet(1, max); /* effectively exprand() */
return (size_t)util_rndGet(1, util_rndGet(1, max));
} }
/* Prefer smaller values here, so use mangle_getLen() */ /* Prefer smaller values here, so use mangle_getLen() */
static inline size_t mangle_getOffSet(run_t *run) { static inline size_t mangle_getOffSet(run_t* run) {
return mangle_getLen(run->dynfile->size) - 1; return mangle_getLen(run->dynfile->size) - 1;
} }
/* Offset which can be equal to the file size */ /* Offset which can be equal to the file size */
static inline size_t mangle_getOffSetPlus1(run_t *run) { static inline size_t mangle_getOffSetPlus1(run_t* run) {
size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE); size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
return mangle_getLen(reqlen) - 1; return mangle_getLen(reqlen) - 1;
} }
static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to, static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_t len) {
size_t len) { if (off_from >= run->dynfile->size) {
return;
if (off_from >= run->dynfile->size) { return; } }
if (off_to >= run->dynfile->size) { return; } if (off_to >= run->dynfile->size) {
if (off_from == off_to) { return; } return;
}
if (off_from == off_to) {
return;
}
size_t len_from = run->dynfile->size - off_from; size_t len_from = run->dynfile->size - off_from;
len = HF_MIN(len, len_from); len = HF_MIN(len, len_from);
@ -115,176 +99,148 @@ static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to,
len = HF_MIN(len, len_to); len = HF_MIN(len, len_to);
memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len); memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
} }
static inline void mangle_Overwrite(run_t *run, size_t off, const uint8_t *src, static inline void mangle_Overwrite(
size_t len, bool printable) { run_t* run, size_t off, const uint8_t* src, size_t len, bool printable) {
if (len == 0) {
if (len == 0) { return; } return;
}
size_t maxToCopy = run->dynfile->size - off; size_t maxToCopy = run->dynfile->size - off;
if (len > maxToCopy) { len = maxToCopy; } if (len > maxToCopy) {
len = maxToCopy;
}
memmove(&run->dynfile->data[off], src, len); memmove(&run->dynfile->data[off], src, len);
if (printable) { util_turnToPrintable(&run->dynfile->data[off], len); } if (printable) {
util_turnToPrintable(&run->dynfile->data[off], len);
}
} }
static inline size_t mangle_Inflate(run_t *run, size_t off, size_t len, static inline size_t mangle_Inflate(run_t* run, size_t off, size_t len, bool printable) {
bool printable) { if (run->dynfile->size >= run->global->mutate.maxInputSz) {
return 0;
if (run->dynfile->size >= run->global->mutate.maxInputSz) { return 0; } }
if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) { if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
len = run->global->mutate.maxInputSz - run->dynfile->size; len = run->global->mutate.maxInputSz - run->dynfile->size;
} }
input_setSize(run, run->dynfile->size + len); input_setSize(run, run->dynfile->size + len);
mangle_Move(run, off, off + len, run->dynfile->size); mangle_Move(run, off, off + len, run->dynfile->size);
if (printable) { memset(&run->dynfile->data[off], ' ', len); } if (printable) {
memset(&run->dynfile->data[off], ' ', len);
return len;
}
static inline void mangle_Insert(run_t *run, size_t off, const uint8_t *val,
size_t len, bool printable) {
len = mangle_Inflate(run, off, len, printable);
mangle_Overwrite(run, off, val, len, printable);
}
static inline void mangle_UseValue(run_t *run, const uint8_t *val, size_t len,
bool printable) {
if (util_rnd64() % 2) {
mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
} else {
mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
} }
return len;
} }
static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) { static inline void mangle_Insert(
run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
len = mangle_Inflate(run, off, len, printable);
mangle_Overwrite(run, off, val, len, printable);
}
static inline void mangle_UseValue(run_t* run, const uint8_t* val, size_t len, bool printable) {
if (util_rnd64() & 1) {
mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
} else {
mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
}
}
static inline void mangle_UseValueAt(
run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
if (util_rnd64() & 1) {
mangle_Overwrite(run, off, val, len, printable);
} else {
mangle_Insert(run, off, val, len, printable);
}
}
static void mangle_MemSwap(run_t* run, bool printable HF_ATTR_UNUSED) {
/* No big deal if those two are overlapping */
size_t off1 = mangle_getOffSet(run); size_t off1 = mangle_getOffSet(run);
size_t maxlen1 = run->dynfile->size - off1; size_t maxlen1 = run->dynfile->size - off1;
size_t off2 = mangle_getOffSet(run); size_t off2 = mangle_getOffSet(run);
size_t maxlen2 = run->dynfile->size - off2; size_t maxlen2 = run->dynfile->size - off2;
size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2)); size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2));
uint8_t *tmpbuf = (uint8_t *)util_Malloc(len);
defer {
free(tmpbuf); if (off1 == off2) {
return;
}; }
memcpy(tmpbuf, &run->dynfile->data[off1], len);
memmove(&run->dynfile->data[off1], &run->dynfile->data[off2], len);
memcpy(&run->dynfile->data[off2], tmpbuf, len);
for (size_t i = 0; i < (len / 2); i++) {
/*
* First - from the head, next from the tail. Don't worry about layout of the overlapping
* part - there's no good solution to that, and it can be left somewhat scrambled,
* while still preserving the entropy
*/
const uint8_t tmp1 = run->dynfile->data[off2 + i];
run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i];
run->dynfile->data[off1 + i] = tmp1;
const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i];
run->dynfile->data[off2 + (len - 1) - i] = run->dynfile->data[off1 + (len - 1) - i];
run->dynfile->data[off1 + (len - 1) - i] = tmp2;
}
} }
static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) { static void mangle_MemCopy(run_t* run, bool printable HF_ATTR_UNUSED) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
size_t len = mangle_getLen(run->dynfile->size - off); size_t len = mangle_getLen(run->dynfile->size - off);
/* Use a temp buf, as Insert/Inflate can change source bytes */ /* Use a temp buf, as Insert/Inflate can change source bytes */
uint8_t *tmpbuf = (uint8_t *)util_Malloc(len); uint8_t* tmpbuf = (uint8_t*)util_Malloc(len);
defer { defer {
free(tmpbuf); free(tmpbuf);
}; };
memmove(tmpbuf, &run->dynfile->data[off], len);
memcpy(tmpbuf, &run->dynfile->data[off], len);
mangle_UseValue(run, tmpbuf, len, printable); mangle_UseValue(run, tmpbuf, len, printable);
} }
static void mangle_Bytes(run_t *run, bool printable) { static void mangle_Bytes(run_t* run, bool printable) {
uint16_t buf; uint16_t buf;
if (printable) { if (printable) {
util_rndBufPrintable((uint8_t*)&buf, sizeof(buf));
util_rndBufPrintable((uint8_t *)&buf, sizeof(buf));
} else { } else {
buf = util_rnd64(); buf = util_rnd64();
} }
/* Overwrite with random 1-2-byte values */ /* Overwrite with random 1-2-byte values */
size_t toCopy = util_rndGet(1, 2); size_t toCopy = util_rndGet(1, 2);
mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable); mangle_UseValue(run, (const uint8_t*)&buf, toCopy, printable);
} }
static void mangle_ByteRepeatOverwrite(run_t *run, bool printable) { static void mangle_ByteRepeat(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
size_t destOff = off + 1; size_t destOff = off + 1;
size_t maxSz = run->dynfile->size - destOff; size_t maxSz = run->dynfile->size - destOff;
/* No space to repeat */ /* No space to repeat */
if (!maxSz) { if (!maxSz) {
mangle_Bytes(run, printable); mangle_Bytes(run, printable);
return; return;
}
size_t len = mangle_getLen(maxSz);
memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
}
static void mangle_ByteRepeatInsert(run_t *run, bool printable) {
size_t off = mangle_getOffSet(run);
size_t destOff = off + 1;
size_t maxSz = run->dynfile->size - destOff;
/* No space to repeat */
if (!maxSz) {
mangle_Bytes(run, printable);
return;
} }
size_t len = mangle_getLen(maxSz); size_t len = mangle_getLen(maxSz);
if (util_rnd64() & 0x1) {
len = mangle_Inflate(run, destOff, len, printable); len = mangle_Inflate(run, destOff, len, printable);
}
memset(&run->dynfile->data[destOff], run->dynfile->data[off], len); memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
} }
static void mangle_Bit(run_t *run, bool printable) { static void mangle_Bit(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7)); run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
if (printable) { util_turnToPrintable(&(run->dynfile->data[off]), 1); } if (printable) {
util_turnToPrintable(&(run->dynfile->data[off]), 1);
}
} }
static const struct { static const struct {
const uint8_t val[8]; const uint8_t val[8];
const size_t size; const size_t size;
} mangleMagicVals[] = { } mangleMagicVals[] = {
/* 1B - No endianness */ /* 1B - No endianness */
{"\x00\x00\x00\x00\x00\x00\x00\x00", 1}, {"\x00\x00\x00\x00\x00\x00\x00\x00", 1},
{"\x01\x00\x00\x00\x00\x00\x00\x00", 1}, {"\x01\x00\x00\x00\x00\x00\x00\x00", 1},
@ -516,208 +472,160 @@ static const struct {
{"\x00\x00\x00\x00\x00\x00\x00\x80", 8}, {"\x00\x00\x00\x00\x00\x00\x00\x80", 8},
{"\x01\x00\x00\x00\x00\x00\x00\x80", 8}, {"\x01\x00\x00\x00\x00\x00\x00\x80", 8},
{"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8}, {"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
}; };
static void mangle_Magic(run_t *run, bool printable) { static void mangle_Magic(run_t* run, bool printable) {
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1); uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
mangle_UseValue(run, mangleMagicVals[choice].val, mangle_UseValue(run, mangleMagicVals[choice].val, mangleMagicVals[choice].size, printable);
mangleMagicVals[choice].size, printable);
} }
static void mangle_StaticDict(run_t *run, bool printable) { static void mangle_StaticDict(run_t* run, bool printable) {
if (run->global->mutate.dictionaryCnt == 0) { if (run->global->mutate.dictionaryCnt == 0) {
mangle_Bytes(run, printable); mangle_Bytes(run, printable);
return; return;
} }
uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1); uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
mangle_UseValue(run, run->global->mutate.dictionary[choice].val, mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
run->global->mutate.dictionary[choice].len, printable); run->global->mutate.dictionary[choice].len, printable);
} }
static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) { static inline const uint8_t* mangle_FeedbackDict(run_t* run, size_t* len) {
if (!run->global->feedback.cmpFeedback) {
if (!run->global->feedback.cmpFeedback) { return NULL; } return NULL;
cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap; }
cmpfeedback_t* cmpf = run->global->feedback.cmpFeedbackMap;
uint32_t cnt = ATOMIC_GET(cmpf->cnt); uint32_t cnt = ATOMIC_GET(cmpf->cnt);
if (cnt == 0) { return NULL; } if (cnt == 0) {
if (cnt > ARRAYSIZE(cmpf->valArr)) { cnt = ARRAYSIZE(cmpf->valArr); } return NULL;
}
if (cnt > ARRAYSIZE(cmpf->valArr)) {
cnt = ARRAYSIZE(cmpf->valArr);
}
uint32_t choice = util_rndGet(0, cnt - 1); uint32_t choice = util_rndGet(0, cnt - 1);
*len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len); *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
if (*len == 0) { return NULL; } if (*len == 0) {
return NULL;
}
return cmpf->valArr[choice].val; return cmpf->valArr[choice].val;
} }
static void mangle_ConstFeedbackDict(run_t *run, bool printable) { static void mangle_ConstFeedbackDict(run_t* run, bool printable) {
size_t len; size_t len;
const uint8_t *val = mangle_FeedbackDict(run, &len); const uint8_t* val = mangle_FeedbackDict(run, &len);
if (val == NULL) { if (val == NULL) {
mangle_Bytes(run, printable); mangle_Bytes(run, printable);
return; return;
} }
mangle_UseValue(run, val, len, printable); mangle_UseValue(run, val, len, printable);
} }
static void mangle_MemSet(run_t *run, bool printable) { static void mangle_MemSet(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
size_t len = mangle_getLen(run->dynfile->size - off); size_t len = mangle_getLen(run->dynfile->size - off);
int val = int val = printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
if (util_rnd64() & 1) {
len = mangle_Inflate(run, off, len, printable);
}
memset(&run->dynfile->data[off], val, len); memset(&run->dynfile->data[off], val, len);
} }
static void mangle_RandomOverwrite(run_t *run, bool printable) { static void mangle_MemClr(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run);
size_t len = mangle_getLen(run->dynfile->size - off);
if (printable) {
util_rndBufPrintable(&run->dynfile->data[off], len);
} else {
util_rndBuf(&run->dynfile->data[off], len);
}
}
static void mangle_RandomInsert(run_t *run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
size_t len = mangle_getLen(run->dynfile->size - off); size_t len = mangle_getLen(run->dynfile->size - off);
int val = printable ? ' ' : 0;
if (util_rnd64() & 1) {
len = mangle_Inflate(run, off, len, printable); len = mangle_Inflate(run, off, len, printable);
if (printable) {
util_rndBufPrintable(&run->dynfile->data[off], len);
} else {
util_rndBuf(&run->dynfile->data[off], len);
} }
memset(&run->dynfile->data[off], val, len);
} }
static inline void mangle_AddSubWithRange(run_t *run, size_t off, size_t varLen, static void mangle_RandomBuf(run_t* run, bool printable) {
uint64_t range, bool printable) { size_t off = mangle_getOffSet(run);
size_t len = mangle_getLen(run->dynfile->size - off);
if (util_rnd64() & 1) {
len = mangle_Inflate(run, off, len, printable);
}
if (printable) {
util_rndBufPrintable(&run->dynfile->data[off], len);
} else {
util_rndBuf(&run->dynfile->data[off], len);
}
}
static inline void mangle_AddSubWithRange(
run_t* run, size_t off, size_t varLen, uint64_t range, bool printable) {
int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range; int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
switch (varLen) { switch (varLen) {
case 1: { case 1: {
run->dynfile->data[off] += delta; run->dynfile->data[off] += delta;
break; break;
} }
case 2: { case 2: {
int16_t val; int16_t val;
memcpy(&val, &run->dynfile->data[off], sizeof(val)); memcpy(&val, &run->dynfile->data[off], sizeof(val));
if (util_rnd64() & 0x1) { if (util_rnd64() & 0x1) {
val += delta; val += delta;
} else { } else {
/* Foreign endianess */ /* Foreign endianess */
val = __builtin_bswap16(val); val = __builtin_bswap16(val);
val += delta; val += delta;
val = __builtin_bswap16(val); val = __builtin_bswap16(val);
} }
mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
break; break;
} }
case 4: { case 4: {
int32_t val; int32_t val;
memcpy(&val, &run->dynfile->data[off], sizeof(val)); memcpy(&val, &run->dynfile->data[off], sizeof(val));
if (util_rnd64() & 0x1) { if (util_rnd64() & 0x1) {
val += delta; val += delta;
} else { } else {
/* Foreign endianess */ /* Foreign endianess */
val = __builtin_bswap32(val); val = __builtin_bswap32(val);
val += delta; val += delta;
val = __builtin_bswap32(val); val = __builtin_bswap32(val);
} }
mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
break; break;
} }
case 8: { case 8: {
int64_t val; int64_t val;
memcpy(&val, &run->dynfile->data[off], sizeof(val)); memcpy(&val, &run->dynfile->data[off], sizeof(val));
if (util_rnd64() & 0x1) { if (util_rnd64() & 0x1) {
val += delta; val += delta;
} else { } else {
/* Foreign endianess */ /* Foreign endianess */
val = __builtin_bswap64(val); val = __builtin_bswap64(val);
val += delta; val += delta;
val = __builtin_bswap64(val); val = __builtin_bswap64(val);
} }
mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
break; break;
} }
default: { default: {
LOG_F("Unknown variable length size: %zu", varLen); LOG_F("Unknown variable length size: %zu", varLen);
} }
} }
} }
static void mangle_AddSub(run_t *run, bool printable) { static void mangle_AddSub(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
/* 1,2,4,8 */ /* 1,2,4,8 */
size_t varLen = 1U << util_rndGet(0, 3); size_t varLen = 1U << util_rndGet(0, 3);
if ((run->dynfile->size - off) < varLen) { varLen = 1; } if ((run->dynfile->size - off) < varLen) {
varLen = 1;
}
uint64_t range; uint64_t range;
switch (varLen) { switch (varLen) {
case 1: case 1:
range = 16; range = 16;
break; break;
@ -732,190 +640,170 @@ static void mangle_AddSub(run_t *run, bool printable) {
break; break;
default: default:
LOG_F("Invalid operand size: %zu", varLen); LOG_F("Invalid operand size: %zu", varLen);
} }
mangle_AddSubWithRange(run, off, varLen, range, printable); mangle_AddSubWithRange(run, off, varLen, range, printable);
} }
static void mangle_IncByte(run_t *run, bool printable) { static void mangle_IncByte(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
if (printable) { if (printable) {
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32; run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
} else { } else {
run->dynfile->data[off] += (uint8_t)1UL; run->dynfile->data[off] += (uint8_t)1UL;
} }
} }
static void mangle_DecByte(run_t *run, bool printable) { static void mangle_DecByte(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
if (printable) { if (printable) {
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32; run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
} else { } else {
run->dynfile->data[off] -= (uint8_t)1UL; run->dynfile->data[off] -= (uint8_t)1UL;
} }
} }
static void mangle_NegByte(run_t *run, bool printable) { static void mangle_NegByte(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
if (printable) { if (printable) {
run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32; run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
} else { } else {
run->dynfile->data[off] = ~(run->dynfile->data[off]); run->dynfile->data[off] = ~(run->dynfile->data[off]);
} }
} }
static void mangle_Expand(run_t *run, bool printable) { static void mangle_Expand(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
size_t len; size_t len;
if (util_rnd64() % 16) { if (util_rnd64() % 16) {
len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off)); len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
} else { } else {
len = mangle_getLen(run->global->mutate.maxInputSz - off); len = mangle_getLen(run->global->mutate.maxInputSz - off);
} }
mangle_Inflate(run, off, len, printable); mangle_Inflate(run, off, len, printable);
} }
static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) { static void mangle_Shrink(run_t* run, bool printable HF_ATTR_UNUSED) {
if (run->dynfile->size <= 2U) {
if (run->dynfile->size <= 2U) { return; } return;
}
size_t off_start = mangle_getOffSet(run); size_t off_start = mangle_getOffSet(run);
size_t len = mangle_LenLeft(run, off_start); size_t len = mangle_LenLeft(run, off_start);
if (len == 0) { return; } if (len == 0) {
if (util_rnd64() % 16) { return;
}
len = mangle_getLen(HF_MIN(16, len)); if (util_rnd64() % 16) {
len = mangle_getLen(HF_MIN(16, len));
} else { } else {
len = mangle_getLen(len);
len = mangle_getLen(len);
} }
size_t off_end = off_start + len; size_t off_end = off_start + len;
size_t len_to_move = run->dynfile->size - off_end; size_t len_to_move = run->dynfile->size - off_end;
mangle_Move(run, off_end, off_start, len_to_move); mangle_Move(run, off_end, off_start, len_to_move);
input_setSize(run, run->dynfile->size - len); input_setSize(run, run->dynfile->size - len);
} }
static void mangle_ASCIINum(run_t* run, bool printable) {
static void mangle_ASCIINum(run_t *run, bool printable) {
size_t len = util_rndGet(2, 8); size_t len = util_rndGet(2, 8);
char buf[20]; char buf[20];
snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64()); snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
mangle_UseValue(run, (const uint8_t *)buf, len, printable); mangle_UseValue(run, (const uint8_t*)buf, len, printable);
} }
static void mangle_ASCIINumChange(run_t *run, bool printable) { static void mangle_ASCIINumChange(run_t* run, bool printable) {
size_t off = mangle_getOffSet(run); size_t off = mangle_getOffSet(run);
/* Find a digit */ /* Find a digit */
for (; off < run->dynfile->size; off++) { for (; off < run->dynfile->size; off++) {
if (isdigit(run->dynfile->data[off])) {
if (isdigit(run->dynfile->data[off])) { break; } break;
} }
}
if (off == run->dynfile->size) { size_t left = run->dynfile->size - off;
if (left == 0) {
mangle_Bytes(run, printable);
return; return;
} }
size_t len = HF_MIN(20, run->dynfile->size - off); size_t len = 0;
char numbuf[21] = {}; uint64_t val = 0;
strncpy(numbuf, (const char *)&run->dynfile->data[off], len); /* 20 is maximum lenght of a string representing a 64-bit unsigned value */
uint64_t val = (uint64_t)strtoull(numbuf, NULL, 10); for (len = 0; (len < 20) && (len < left); len++) {
char c = run->dynfile->data[off + len];
switch (util_rndGet(0, 5)) { if (!isdigit(c)) {
break;
}
val *= 10;
val += (c - '0');
}
switch (util_rndGet(0, 7)) {
case 0: case 0:
val += util_rndGet(1, 256); val++;
break; break;
case 1: case 1:
val -= util_rndGet(1, 256); val--;
break; break;
case 2: case 2:
val *= util_rndGet(1, 256); val *= 2;
break; break;
case 3: case 3:
val /= util_rndGet(1, 256); val /= 2;
break; break;
case 4: case 4:
val = ~(val); val = util_rnd64();
break; break;
case 5: case 5:
val = util_rnd64(); val += util_rndGet(1, 256);
break;
case 6:
val -= util_rndGet(1, 256);
break;
case 7:
val = ~(val);
break; break;
default: default:
LOG_F("Invalid choice"); LOG_F("Invalid choice");
}; };
len = HF_MIN((size_t)snprintf(numbuf, sizeof(numbuf), "%" PRIu64, val), len); char buf[20];
mangle_Overwrite(run, off, (const uint8_t *)numbuf, len, printable); snprintf(buf, sizeof(buf), "%-19" PRIu64, val);
mangle_UseValueAt(run, off, (const uint8_t*)buf, len, printable);
} }
static void mangle_Splice(run_t *run, bool printable) { static void mangle_Splice(run_t* run, bool printable) {
if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) {
const uint8_t *buf;
size_t sz = input_getRandomInputAsBuf(run, &buf);
if (!sz) {
mangle_Bytes(run, printable); mangle_Bytes(run, printable);
return; return;
}
size_t sz = 0;
const uint8_t* buf = input_getRandomInputAsBuf(run, &sz);
if (!buf) {
LOG_E("input_getRandomInputAsBuf() returned no input");
mangle_Bytes(run, printable);
return;
}
if (!sz) {
mangle_Bytes(run, printable);
return;
} }
size_t remoteOff = mangle_getLen(sz) - 1; size_t remoteOff = mangle_getLen(sz) - 1;
size_t len = mangle_getLen(sz - remoteOff); size_t len = mangle_getLen(sz - remoteOff);
mangle_UseValue(run, &buf[remoteOff], len, printable); mangle_UseValue(run, &buf[remoteOff], len, printable);
} }
static void mangle_Resize(run_t *run, bool printable) { static void mangle_Resize(run_t* run, bool printable) {
ssize_t oldsz = run->dynfile->size; ssize_t oldsz = run->dynfile->size;
ssize_t newsz = 0; ssize_t newsz = 0;
uint64_t choice = util_rndGet(0, 32); uint64_t choice = util_rndGet(0, 32);
switch (choice) { switch (choice) {
case 0: /* Set new size arbitrarily */ case 0: /* Set new size arbitrarily */
newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz); newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
break; break;
@ -937,33 +825,24 @@ static void mangle_Resize(run_t *run, bool printable) {
default: default:
LOG_F("Illegal value from util_rndGet: %" PRIu64, choice); LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
break; break;
} }
if (newsz < 1) {
if (newsz < 1) { newsz = 1; } newsz = 1;
}
if (newsz > (ssize_t)run->global->mutate.maxInputSz) { if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
newsz = run->global->mutate.maxInputSz; newsz = run->global->mutate.maxInputSz;
} }
input_setSize(run, (size_t)newsz); input_setSize(run, (size_t)newsz);
if (newsz > oldsz) { if (newsz > oldsz) {
if (printable) {
if (printable) { memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); } memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz);
}
} }
} }
void mangle_mangleContent(run_t *run, int speed_factor) { void mangle_mangleContent(run_t* run, int speed_factor) {
static void (*const mangleFuncs[])(run_t * run, bool printable) = { static void (*const mangleFuncs[])(run_t * run, bool printable) = {
/* Every *Insert or Expand expands file, so add more Shrink's */
mangle_Shrink,
mangle_Shrink,
mangle_Shrink,
mangle_Shrink, mangle_Shrink,
mangle_Expand, mangle_Expand,
mangle_Bit, mangle_Bit,
@ -972,66 +851,57 @@ void mangle_mangleContent(run_t *run, int speed_factor) {
mangle_NegByte, mangle_NegByte,
mangle_AddSub, mangle_AddSub,
mangle_MemSet, mangle_MemSet,
mangle_MemClr,
mangle_MemSwap, mangle_MemSwap,
mangle_MemCopy, mangle_MemCopy,
mangle_Bytes, mangle_Bytes,
mangle_ASCIINum, mangle_ASCIINum,
mangle_ASCIINumChange, mangle_ASCIINumChange,
mangle_ByteRepeatOverwrite, mangle_ByteRepeat,
mangle_ByteRepeatInsert,
mangle_Magic, mangle_Magic,
mangle_StaticDict, mangle_StaticDict,
mangle_ConstFeedbackDict, mangle_ConstFeedbackDict,
mangle_RandomOverwrite, mangle_RandomBuf,
mangle_RandomInsert,
mangle_Splice, mangle_Splice,
}; };
if (run->mutationsPerRun == 0U) { return; } if (run->mutationsPerRun == 0U) {
return;
}
if (run->dynfile->size == 0U) { if (run->dynfile->size == 0U) {
mangle_Resize(run, /* printable= */ run->global->cfg.only_printable); mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
} }
uint64_t changesCnt; uint64_t changesCnt = run->global->mutate.mutationsPerRun;
if (speed_factor < 5) { if (speed_factor < 5) {
changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun); changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
} else if (speed_factor < 10) { } else if (speed_factor < 10) {
changesCnt = run->global->mutate.mutationsPerRun; changesCnt = run->global->mutate.mutationsPerRun;
} else { } else {
changesCnt = HF_MIN(speed_factor, 10);
changesCnt = HF_MIN(speed_factor, 12); changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5));
changesCnt = HF_MAX(changesCnt, run->global->mutate.mutationsPerRun);
} }
/* If last coverage acquisition was more than 5 secs ago, use splicing more /* If last coverage acquisition was more than 5 secs ago, use splicing more frequently */
* frequently */
if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) { if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
if (util_rnd64() & 0x1) {
if (util_rnd64() % 2) {
mangle_Splice(run, run->global->cfg.only_printable); mangle_Splice(run, run->global->cfg.only_printable);
} }
} }
for (uint64_t x = 0; x < changesCnt; x++) { for (uint64_t x = 0; x < changesCnt; x++) {
if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) {
/*
* mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback dictionary
* exists. If so, give it 50% chance of being used among all mangling functions.
*/
mangle_ConstFeedbackDict(run, /* printable= */ run->global->cfg.only_printable);
} else {
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1); uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable); mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable);
}
} }
wmb(); wmb();
} }