diff options
Diffstat (limited to 'custom_mutators/honggfuzz/mangle.c')
-rw-r--r-- | custom_mutators/honggfuzz/mangle.c | 1039 |
1 files changed, 1039 insertions, 0 deletions
diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c new file mode 100644 index 00000000..05e0dcfa --- /dev/null +++ b/custom_mutators/honggfuzz/mangle.c @@ -0,0 +1,1039 @@ +/* + * + * honggfuzz - run->dynfile->datafer mangling routines + * ----------------------------------------- + * + * Author: + * Robert Swiecki <swiecki@google.com> + * + * Copyright 2010-2018 by Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ + +#include "mangle.h" + +#include <ctype.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <time.h> + +#include "input.h" +#include "libhfcommon/common.h" +#include "libhfcommon/log.h" +#include "libhfcommon/util.h" + +static inline size_t mangle_LenLeft(run_t *run, size_t off) { + + if (off >= run->dynfile->size) { + + LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size); + + } + + return (run->dynfile->size - off - 1); + +} + +/* Get a random value between <1:max> with x^2 distribution */ +static inline size_t mangle_getLen(size_t max) { + + if (max > _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; } + + const uint64_t max2 = (uint64_t)max * max; + const uint64_t max3 = (uint64_t)max * max * max; + const uint64_t rnd = util_rndGet(1, max2 - 1); + + uint64_t ret = rnd * rnd; + ret /= max3; + ret += 1; + + if (ret < 1) { + + LOG_F("ret (%" PRIu64 ") < 1, max:%zu, rnd:%" PRIu64, ret, max, rnd); + + } + + if (ret > max) { + + LOG_F("ret (%" PRIu64 ") > max (%zu), rnd:%" PRIu64, ret, max, rnd); + + } + + return (size_t)ret; + +} + +/* Prefer smaller values here, so use mangle_getLen() */ +static inline size_t mangle_getOffSet(run_t *run) { + + return mangle_getLen(run->dynfile->size) - 1; + +} + +/* Offset which can be equal to the file size */ +static inline size_t mangle_getOffSetPlus1(run_t *run) { + + size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE); + return mangle_getLen(reqlen) - 1; + +} + +static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to, + size_t len) { + + if (off_from >= run->dynfile->size) { return; } + if (off_to >= run->dynfile->size) { return; } + if (off_from == off_to) { return; } + + size_t len_from = run->dynfile->size - off_from; + len = HF_MIN(len, len_from); + + size_t len_to = run->dynfile->size - off_to; + len = HF_MIN(len, len_to); + + 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, + size_t len, bool printable) { + + if (len == 0) { return; } + size_t maxToCopy = run->dynfile->size - off; + if (len > maxToCopy) { len = maxToCopy; } + + memmove(&run->dynfile->data[off], src, 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, + bool printable) { + + if (run->dynfile->size >= run->global->mutate.maxInputSz) { return 0; } + if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) { + + len = run->global->mutate.maxInputSz - run->dynfile->size; + + } + + input_setSize(run, run->dynfile->size + len); + mangle_Move(run, off, off + len, run->dynfile->size); + 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); + + } + +} + +static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) { + + size_t off1 = mangle_getOffSet(run); + size_t maxlen1 = run->dynfile->size - off1; + + size_t off2 = mangle_getOffSet(run); + size_t maxlen2 = run->dynfile->size - off2; + + size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2)); + uint8_t *tmpbuf = (uint8_t *)util_Malloc(len); + defer { + + free(tmpbuf); + + }; + + memcpy(tmpbuf, &run->dynfile->data[off1], len); + memmove(&run->dynfile->data[off1], &run->dynfile->data[off2], len); + memcpy(&run->dynfile->data[off2], tmpbuf, len); + +} + +static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) { + + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + + /* Use a temp buf, as Insert/Inflate can change source bytes */ + uint8_t *tmpbuf = (uint8_t *)util_Malloc(len); + defer { + + free(tmpbuf); + + }; + + memcpy(tmpbuf, &run->dynfile->data[off], len); + + mangle_UseValue(run, tmpbuf, len, printable); + +} + +static void mangle_Bytes(run_t *run, bool printable) { + + uint16_t buf; + if (printable) { + + util_rndBufPrintable((uint8_t *)&buf, sizeof(buf)); + + } else { + + buf = util_rnd64(); + + } + + /* Overwrite with random 1-2-byte values */ + size_t toCopy = util_rndGet(1, 2); + mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable); + +} + +static void mangle_ByteRepeatOverwrite(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); + 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); + len = mangle_Inflate(run, destOff, len, printable); + memset(&run->dynfile->data[destOff], run->dynfile->data[off], len); + +} + +static void mangle_Bit(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7)); + if (printable) { util_turnToPrintable(&(run->dynfile->data[off]), 1); } + +} + +static const struct { + + const uint8_t val[8]; + const size_t size; + +} mangleMagicVals[] = { + + /* 1B - No endianness */ + {"\x00\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x01\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x02\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x03\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x04\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x05\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x06\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x07\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x08\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x09\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x0A\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x0B\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x0C\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x0D\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x0E\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x0F\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x10\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x20\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x40\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x7E\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x7F\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x80\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\x81\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\xC0\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\xFE\x00\x00\x00\x00\x00\x00\x00", 1}, + {"\xFF\x00\x00\x00\x00\x00\x00\x00", 1}, + /* 2B - NE */ + {"\x00\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x01\x01\x00\x00\x00\x00\x00\x00", 2}, + {"\x80\x80\x00\x00\x00\x00\x00\x00", 2}, + {"\xFF\xFF\x00\x00\x00\x00\x00\x00", 2}, + /* 2B - BE */ + {"\x00\x01\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x02\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x03\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x04\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x05\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x06\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x07\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x08\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x09\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x0A\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x0B\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x0C\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x0D\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x0E\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x0F\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x10\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x20\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x40\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x7E\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x7F\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x80\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x81\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\xC0\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\xFE\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\xFF\x00\x00\x00\x00\x00\x00", 2}, + {"\x7E\xFF\x00\x00\x00\x00\x00\x00", 2}, + {"\x7F\xFF\x00\x00\x00\x00\x00\x00", 2}, + {"\x80\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x80\x01\x00\x00\x00\x00\x00\x00", 2}, + {"\xFF\xFE\x00\x00\x00\x00\x00\x00", 2}, + /* 2B - LE */ + {"\x00\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x01\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x02\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x03\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x04\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x05\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x06\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x07\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x08\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x09\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x0A\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x0B\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x0C\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x0D\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x0E\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x0F\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x10\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x20\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x40\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x7E\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x7F\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x80\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\x81\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\xC0\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\xFE\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\xFF\x00\x00\x00\x00\x00\x00\x00", 2}, + {"\xFF\x7E\x00\x00\x00\x00\x00\x00", 2}, + {"\xFF\x7F\x00\x00\x00\x00\x00\x00", 2}, + {"\x00\x80\x00\x00\x00\x00\x00\x00", 2}, + {"\x01\x80\x00\x00\x00\x00\x00\x00", 2}, + {"\xFE\xFF\x00\x00\x00\x00\x00\x00", 2}, + /* 4B - NE */ + {"\x00\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x01\x01\x01\x01\x00\x00\x00\x00", 4}, + {"\x80\x80\x80\x80\x00\x00\x00\x00", 4}, + {"\xFF\xFF\xFF\xFF\x00\x00\x00\x00", 4}, + /* 4B - BE */ + {"\x00\x00\x00\x01\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x02\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x03\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x04\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x05\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x06\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x07\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x08\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x09\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x0A\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x0B\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x0C\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x0D\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x0E\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x0F\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x10\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x20\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x40\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x7E\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x7F\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x80\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x81\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\xC0\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\xFE\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\xFF\x00\x00\x00\x00", 4}, + {"\x7E\xFF\xFF\xFF\x00\x00\x00\x00", 4}, + {"\x7F\xFF\xFF\xFF\x00\x00\x00\x00", 4}, + {"\x80\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x80\x00\x00\x01\x00\x00\x00\x00", 4}, + {"\xFF\xFF\xFF\xFE\x00\x00\x00\x00", 4}, + /* 4B - LE */ + {"\x00\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x01\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x02\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x03\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x04\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x05\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x06\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x07\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x08\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x09\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x0A\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x0B\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x0C\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x0D\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x0E\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x0F\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x10\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x20\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x40\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x7E\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x7F\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x80\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\x81\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\xC0\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\xFE\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\xFF\x00\x00\x00\x00\x00\x00\x00", 4}, + {"\xFF\xFF\xFF\x7E\x00\x00\x00\x00", 4}, + {"\xFF\xFF\xFF\x7F\x00\x00\x00\x00", 4}, + {"\x00\x00\x00\x80\x00\x00\x00\x00", 4}, + {"\x01\x00\x00\x80\x00\x00\x00\x00", 4}, + {"\xFE\xFF\xFF\xFF\x00\x00\x00\x00", 4}, + /* 8B - NE */ + {"\x00\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x01\x01\x01\x01\x01\x01\x01\x01", 8}, + {"\x80\x80\x80\x80\x80\x80\x80\x80", 8}, + {"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8}, + /* 8B - BE */ + {"\x00\x00\x00\x00\x00\x00\x00\x01", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x02", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x03", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x04", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x05", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x06", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x07", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x08", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x09", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x0A", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x0B", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x0C", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x0D", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x0E", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x0F", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x10", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x20", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x40", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x7E", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x7F", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x80", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\x81", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\xC0", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\xFE", 8}, + {"\x00\x00\x00\x00\x00\x00\x00\xFF", 8}, + {"\x7E\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8}, + {"\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8}, + {"\x80\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x80\x00\x00\x00\x00\x00\x00\x01", 8}, + {"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE", 8}, + /* 8B - LE */ + {"\x00\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x01\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x02\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x03\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x04\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x05\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x06\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x07\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x08\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x09\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x0A\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x0B\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x0C\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x0D\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x0E\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x0F\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x10\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x20\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x40\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x7E\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x7F\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x80\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\x81\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\xC0\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\xFE\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\xFF\x00\x00\x00\x00\x00\x00\x00", 8}, + {"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7E", 8}, + {"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", 8}, + {"\x00\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}, + +}; + +static void mangle_Magic(run_t *run, bool printable) { + + uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1); + mangle_UseValue(run, mangleMagicVals[choice].val, + mangleMagicVals[choice].size, printable); + +} + +static void mangle_StaticDict(run_t *run, bool printable) { + + if (run->global->mutate.dictionaryCnt == 0) { + + mangle_Bytes(run, printable); + return; + + } + + uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1); + mangle_UseValue(run, run->global->mutate.dictionary[choice].val, + run->global->mutate.dictionary[choice].len, printable); + +} + +static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) { + + if (!run->global->feedback.cmpFeedback) { return NULL; } + cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap; + uint32_t cnt = ATOMIC_GET(cmpf->cnt); + if (cnt == 0) { return NULL; } + if (cnt > ARRAYSIZE(cmpf->valArr)) { cnt = ARRAYSIZE(cmpf->valArr); } + uint32_t choice = util_rndGet(0, cnt - 1); + *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len); + if (*len == 0) { return NULL; } + return cmpf->valArr[choice].val; + +} + +static void mangle_ConstFeedbackDict(run_t *run, bool printable) { + + size_t len; + const uint8_t *val = mangle_FeedbackDict(run, &len); + if (val == NULL) { + + mangle_Bytes(run, printable); + return; + + } + + mangle_UseValue(run, val, len, printable); + +} + +static void mangle_MemSet(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + int val = + printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX); + + memset(&run->dynfile->data[off], val, len); + +} + +static void mangle_RandomOverwrite(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 len = mangle_getLen(run->dynfile->size - off); + + 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; + + switch (varLen) { + + case 1: { + + run->dynfile->data[off] += delta; + break; + + } + + case 2: { + + int16_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + + val += delta; + + } else { + + /* Foreign endianess */ + val = __builtin_bswap16(val); + val += delta; + val = __builtin_bswap16(val); + + } + + mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); + break; + + } + + case 4: { + + int32_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + + val += delta; + + } else { + + /* Foreign endianess */ + val = __builtin_bswap32(val); + val += delta; + val = __builtin_bswap32(val); + + } + + mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); + break; + + } + + case 8: { + + int64_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + + val += delta; + + } else { + + /* Foreign endianess */ + val = __builtin_bswap64(val); + val += delta; + val = __builtin_bswap64(val); + + } + + mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); + break; + + } + + default: { + + LOG_F("Unknown variable length size: %zu", varLen); + + } + + } + +} + +static void mangle_AddSub(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + + /* 1,2,4,8 */ + size_t varLen = 1U << util_rndGet(0, 3); + if ((run->dynfile->size - off) < varLen) { varLen = 1; } + + uint64_t range; + switch (varLen) { + + case 1: + range = 16; + break; + case 2: + range = 4096; + break; + case 4: + range = 1048576; + break; + case 8: + range = 268435456; + break; + default: + LOG_F("Invalid operand size: %zu", varLen); + + } + + mangle_AddSubWithRange(run, off, varLen, range, printable); + +} + +static void mangle_IncByte(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + if (printable) { + + run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32; + + } else { + + run->dynfile->data[off] += (uint8_t)1UL; + + } + +} + +static void mangle_DecByte(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + if (printable) { + + run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32; + + } else { + + run->dynfile->data[off] -= (uint8_t)1UL; + + } + +} + +static void mangle_NegByte(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + if (printable) { + + run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32; + + } else { + + run->dynfile->data[off] = ~(run->dynfile->data[off]); + + } + +} + +static void mangle_Expand(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + size_t len; + if (util_rnd64() % 16) { + + len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off)); + + } else { + + len = mangle_getLen(run->global->mutate.maxInputSz - off); + + } + + mangle_Inflate(run, off, len, printable); + +} + +static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) { + + if (run->dynfile->size <= 2U) { return; } + + size_t off_start = mangle_getOffSet(run); + size_t len = mangle_LenLeft(run, off_start); + if (len == 0) { return; } + if (util_rnd64() % 16) { + + len = mangle_getLen(HF_MIN(16, len)); + + } else { + + len = mangle_getLen(len); + + } + + size_t off_end = off_start + len; + size_t len_to_move = run->dynfile->size - off_end; + + mangle_Move(run, off_end, off_start, len_to_move); + input_setSize(run, run->dynfile->size - len); + +} + +static void mangle_ASCIINum(run_t *run, bool printable) { + + size_t len = util_rndGet(2, 8); + + char buf[20]; + snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64()); + + mangle_UseValue(run, (const uint8_t *)buf, len, printable); + +} + +static void mangle_ASCIINumChange(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + + /* Find a digit */ + for (; off < run->dynfile->size; off++) { + + if (isdigit(run->dynfile->data[off])) { break; } + + } + + if (off == run->dynfile->size) { + + mangle_Bytes(run, printable); + return; + + } + + size_t len = HF_MIN(20, run->dynfile->size - off); + char numbuf[21] = {}; + strncpy(numbuf, (const char *)&run->dynfile->data[off], len); + uint64_t val = (uint64_t)strtoull(numbuf, NULL, 10); + + switch (util_rndGet(0, 5)) { + + case 0: + val += util_rndGet(1, 256); + break; + case 1: + val -= util_rndGet(1, 256); + break; + case 2: + val *= util_rndGet(1, 256); + break; + case 3: + val /= util_rndGet(1, 256); + break; + case 4: + val = ~(val); + break; + case 5: + val = util_rnd64(); + break; + default: + LOG_F("Invalid choice"); + + }; + + len = HF_MIN((size_t)snprintf(numbuf, sizeof(numbuf), "%" PRIu64, val), len); + mangle_Overwrite(run, off, (const uint8_t *)numbuf, len, printable); + +} + +static void mangle_Splice(run_t *run, bool printable) { + + const uint8_t *buf; + size_t sz = input_getRandomInputAsBuf(run, &buf); + if (!sz) { + + mangle_Bytes(run, printable); + return; + + } + + size_t remoteOff = mangle_getLen(sz) - 1; + size_t len = mangle_getLen(sz - remoteOff); + mangle_UseValue(run, &buf[remoteOff], len, printable); + +} + +static void mangle_Resize(run_t *run, bool printable) { + + ssize_t oldsz = run->dynfile->size; + ssize_t newsz = 0; + + uint64_t choice = util_rndGet(0, 32); + switch (choice) { + + case 0: /* Set new size arbitrarily */ + newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz); + break; + case 1 ... 4: /* Increase size by a small value */ + newsz = oldsz + (ssize_t)util_rndGet(0, 8); + break; + case 5: /* Increase size by a larger value */ + newsz = oldsz + (ssize_t)util_rndGet(9, 128); + break; + case 6 ... 9: /* Decrease size by a small value */ + newsz = oldsz - (ssize_t)util_rndGet(0, 8); + break; + case 10: /* Decrease size by a larger value */ + newsz = oldsz - (ssize_t)util_rndGet(9, 128); + break; + case 11 ... 32: /* Do nothing */ + newsz = oldsz; + break; + default: + LOG_F("Illegal value from util_rndGet: %" PRIu64, choice); + break; + + } + + if (newsz < 1) { newsz = 1; } + if (newsz > (ssize_t)run->global->mutate.maxInputSz) { + + newsz = run->global->mutate.maxInputSz; + + } + + input_setSize(run, (size_t)newsz); + if (newsz > oldsz) { + + if (printable) { memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); } + + } + +} + +void mangle_mangleContent(run_t *run, int speed_factor) { + + 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_Expand, + mangle_Bit, + mangle_IncByte, + mangle_DecByte, + mangle_NegByte, + mangle_AddSub, + mangle_MemSet, + mangle_MemSwap, + mangle_MemCopy, + mangle_Bytes, + mangle_ASCIINum, + mangle_ASCIINumChange, + mangle_ByteRepeatOverwrite, + mangle_ByteRepeatInsert, + mangle_Magic, + mangle_StaticDict, + mangle_ConstFeedbackDict, + mangle_RandomOverwrite, + mangle_RandomInsert, + mangle_Splice, + + }; + + if (run->mutationsPerRun == 0U) { return; } + if (run->dynfile->size == 0U) { + + mangle_Resize(run, /* printable= */ run->global->cfg.only_printable); + + } + + uint64_t changesCnt = run->global->mutate.mutationsPerRun; + + if (speed_factor < 5) { + + changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun); + + } else if (speed_factor < 10) { + + changesCnt = run->global->mutate.mutationsPerRun; + + } else { + + changesCnt = HF_MIN(speed_factor, 12); + changesCnt = HF_MAX(changesCnt, run->global->mutate.mutationsPerRun); + + } + + /* If last coverage acquisition was more than 5 secs ago, use splicing more + * frequently */ + if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) { + + if (util_rnd64() % 2) { + + mangle_Splice(run, run->global->cfg.only_printable); + + } + + } + + for (uint64_t x = 0; x < changesCnt; x++) { + + uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1); + mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable); + + } + + wmb(); + +} + |