VirtualBox

Ignore:
Timestamp:
Feb 27, 2019 1:17:24 PM (6 years ago)
Author:
vboxsync
Message:

Runtime/fuzz: Rewriting the core fuzzed input generator.

The new implementation stores only changes between mutations and not the
complete input. This saves memory (at the cost of a bit of increased complexity
when generating the input) and allows to generate mutations when no initial corpus
data is available which is useful when trying to fuzz data streams like network connections.

There are two modes when creating a new fuzzing context:

  • BLOB is used for input data like files where an initial corpus is available
  • STREAM is used for data streams like network connections
Location:
trunk/src/VBox/Runtime/common/fuzz
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fuzz/fuzz-observer.cpp

    r76553 r77482  
    875875        else if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN)
    876876        {
    877             rc = RTFuzzInputQueryData(pObsThrd->hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft);
     877            rc = RTFuzzInputQueryBlobData(pObsThrd->hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft);
    878878            if (RT_SUCCESS(rc))
    879879                rc = rtFuzzObsExecCtxArgvPrepare(pThis, pExecCtx, NULL);
     
    907907            else
    908908                AssertFailed();
     909
     910            ASMAtomicXchgBool(&pObsThrd->fKeepInput, true);
    909911
    910912            if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE)
     
    10661068
    10671069
    1068 RTDECL(int) RTFuzzObsCreate(PRTFUZZOBS phFuzzObs)
     1070RTDECL(int) RTFuzzObsCreate(PRTFUZZOBS phFuzzObs, RTFUZZCTXTYPE enmType)
    10691071{
    10701072    AssertPtrReturn(phFuzzObs, VERR_INVALID_POINTER);
     
    10871089        pThis->Stats.cFuzzedInputsHang   = 0;
    10881090        pThis->Stats.cFuzzedInputsCrash  = 0;
    1089         rc = RTFuzzCtxCreate(&pThis->hFuzzCtx);
     1091        rc = RTFuzzCtxCreate(&pThis->hFuzzCtx, enmType);
    10901092        if (RT_SUCCESS(rc))
    10911093        {
  • trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp

    r76553 r77482  
    4444#include <iprt/path.h>
    4545#include <iprt/rand.h>
     46#include <iprt/semaphore.h>
    4647#include <iprt/string.h>
    4748#include <iprt/time.h>
     
    5758/** Pointer to the internal fuzzer state. */
    5859typedef struct RTFUZZCTXINT *PRTFUZZCTXINT;
    59 
    60 /**
    61  * A fuzzing input seed.
    62  */
    63 typedef struct RTFUZZINPUTINT
     60/** Pointer to a fuzzed mutation. */
     61typedef struct RTFUZZMUTATION *PRTFUZZMUTATION;
     62/** Pointer to a fuzzed mutation pointer. */
     63typedef PRTFUZZMUTATION *PPRTFUZZMUTATION;
     64/** Pointer to a const mutation. */
     65typedef const struct RTFUZZMUTATION *PCRTFUZZMUTATION;
     66
     67
     68/**
     69 * Mutator preparation callback.
     70 *
     71 * @returns IPRT status code.
     72 * @param   pThis               The fuzzer context instance.
     73 * @param   offStart            Where the mutation should start.
     74 * @param   pMutationParent     The parent mutation to start working from.
     75 * @param   ppMutation          Where to store the created mutation on success.
     76 */
     77typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATORPREP(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     78                                                 PPRTFUZZMUTATION ppMutation);
     79/** Pointer to a mutator preparation callback. */
     80typedef FNRTFUZZCTXMUTATORPREP *PFNRTFUZZCTXMUTATORPREP;
     81
     82
     83/**
     84 * Mutator execution callback.
     85 *
     86 * @returns IPRT status code.
     87 * @param   pThis               The fuzzer context instance.
     88 * @param   pMutation           The mutation to work on.
     89 * @param   pbBuf               The buffer to work on.
     90 * @param   cbBuf               Size of the remaining buffer.
     91 */
     92typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXEC(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     93                                                 uint8_t *pbBuf, size_t cbBuf);
     94/** Pointer to a mutator execution callback. */
     95typedef FNRTFUZZCTXMUTATOREXEC *PFNRTFUZZCTXMUTATOREXEC;
     96
     97
     98/**
     99 * A fuzzing mutator descriptor.
     100 */
     101typedef struct RTFUZZMUTATOR
     102{
     103    /** Id of the mutator. */
     104    const char                  *pszId;
     105    /** Mutator description. */
     106    const char                  *pszDesc;
     107    /** Additional flags for the mutator, controlling the behavior. */
     108    uint64_t                    fFlags;
     109    /** The preparation callback. */
     110    PFNRTFUZZCTXMUTATORPREP     pfnPrep;
     111    /** The execution callback. */
     112    PFNRTFUZZCTXMUTATOREXEC     pfnExec;
     113} RTFUZZMUTATOR;
     114/** Pointer to a fuzzing mutator descriptor. */
     115typedef RTFUZZMUTATOR *PRTFUZZMUTATOR;
     116/** Pointer to a const fuzzing mutator descriptor. */
     117typedef const RTFUZZMUTATOR *PCRTFUZZMUTATOR;
     118
     119/** Mutator always works from the end of the buffer (no starting offset generation). */
     120#define RTFUZZMUTATOR_F_END_OF_BUF          RT_BIT_64(0)
     121/** Default flags. */
     122#define RTFUZZMUTATOR_F_DEFAULT             (0)
     123
     124
     125/**
     126 * A fuzzed mutation.
     127 */
     128typedef struct RTFUZZMUTATION
    64129{
    65130    /** The AVL tree core. */
    66131    AVLU64NODECORE              Core;
    67     /** Node for the global list. */
    68     RTLISTNODE                  NdInputs;
     132    /** Magic identifying this structure. */
     133    uint32_t                    u32Magic;
    69134    /** Reference counter. */
    70135    volatile uint32_t           cRefs;
    71 /** @todo add magic here (unused padding space on 64-bit hosts). */
     136    /** The fuzzer this mutation belongs to. */
     137    PRTFUZZCTXINT               pFuzzer;
     138    /** Parent mutation (reference is held), NULL means root or original data. */
     139    PCRTFUZZMUTATION            pMutationParent;
     140    /** Mutation level. */
     141    uint32_t                    iLvl;
     142    /** The mutator causing this mutation, NULL if original input data. */
     143    PCRTFUZZMUTATOR             pMutator;
     144    /** Byte offset where the mutation starts. */
     145    uint64_t                    offMutation;
     146    /** Size of the generated input data in bytes after the mutation was applied. */
     147    size_t                      cbInput;
     148    /** Mutation dependent data. */
     149    union
     150    {
     151        /** Array of bytes making up the corups, variable in size. */
     152        uint8_t                 abCorpus[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
     153        /** Bit flip mutation, which bit to flip. */
     154        uint32_t                idxBitFlip;
     155        /** Byte replace, the byte to replace with. */
     156        uint8_t                 bByteReplace;
     157        /** Array of bytes to insert/append, variable in size. */
     158        uint8_t                 abAdd[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
     159    } u;
     160} RTFUZZMUTATION;
     161
     162
     163/**
     164 * A fuzzing input seed.
     165 */
     166typedef struct RTFUZZINPUTINT
     167{
     168    /** Magic identifying this structure. */
     169    uint32_t                    u32Magic;
     170    /** Reference counter. */
     171    volatile uint32_t           cRefs;
    72172    /** The fuzzer this input belongs to. */
    73173    PRTFUZZCTXINT               pFuzzer;
    74     /** Complete MD5 hash of the input data. */
    75     uint8_t                     abMd5Hash[RTMD5_HASH_SIZE];
    76     /** Size of the input data. */
    77     size_t                      cbInput;
    78     /** Input data - variable in size. */
    79     uint8_t                     abInput[1];
     174    /** The top mutation to work from (reference held). */
     175    PRTFUZZMUTATION             pMutationTop;
     176    /** Fuzzer context type dependent data. */
     177    union
     178    {
     179        /** Blob data. */
     180        struct
     181        {
     182            /** Size to allocate initially. */
     183            size_t              cbAlloc;
     184            /** Input data size. */
     185            size_t              cbInput;
     186            /** Pointer to the input data if created. */
     187            void                *pvInput;
     188        } Blob;
     189        /** Stream state. */
     190        struct
     191        {
     192            /** Number of bytes seen so far. */
     193            size_t              cbSeen;
     194        } Stream;
     195    } u;
     196    /** Array holding all the individual mutations, variable in size. */
     197    PCRTFUZZMUTATION            apMutations[1];
    80198} RTFUZZINPUTINT;
    81199/** Pointer to the internal input state. */
     
    84202typedef PRTFUZZINPUTINT *PPRTFUZZINPUTINT;
    85203
    86 
    87 /**
    88  * Intermediate indexing structure.
    89  */
    90 typedef struct RTFUZZINTERMEDIATE
    91 {
    92     /** The AVL tree core. */
    93     AVLU64NODECORE              Core;
    94     /** The AVL tree for indexing the input seeds (keyed by the lower half of the MD5). */
    95     AVLU64TREE                  TreeSeedsLow;
    96 } RTFUZZINTERMEDIATE;
    97 /** Pointer to an intermediate indexing state. */
    98 typedef RTFUZZINTERMEDIATE *PRTFUZZINTERMEDIATE;
    99 /** Pointer to an intermediate indexing state pointer. */
    100 typedef PRTFUZZINTERMEDIATE *PPRTFUZZINTERMEDIATE;
    101204
    102205/**
     
    111214    /** The random number generator. */
    112215    RTRAND                      hRand;
    113     /** The AVL tree for indexing the input seeds (keyed by the upper half of the MD5). */
    114     AVLU64TREE                  TreeSeedsHigh;
    115     /** Sequential list of all inputs. */
    116     RTLISTANCHOR                LstInputs;
     216    /** Fuzzing context type. */
     217    RTFUZZCTXTYPE               enmType;
     218    /** Semaphore protecting the mutations tree. */
     219    RTSEMRW                     hSemRwMutations;
     220    /** The AVL tree for indexing the mutations (keyed by counter). */
     221    AVLU64TREE                  TreeMutations;
    117222    /** Number of inputs currently in the tree. */
    118     uint32_t                    cInputs;
     223    volatile uint64_t           cMutations;
    119224    /** The maximum size of one input seed to generate. */
    120225    size_t                      cbInputMax;
    121226    /** Behavioral flags. */
    122227    uint32_t                    fFlagsBehavioral;
     228    /** Number of enabled mutators. */
     229    uint32_t                    cMutators;
     230    /** Pointer to the mutator descriptors. */
     231    PRTFUZZMUTATOR              paMutators;
     232    /** Total number of bytes of memory currently allocated in total for this context. */
     233    volatile size_t             cbMemTotal;
    123234} RTFUZZCTXINT;
    124 
    125 
    126 /**
    127  * Available mutators enum.
    128  */
    129 typedef enum RTFUZZCTXMUTATOR
    130 {
    131     /** Invalid mutator, not used. */
    132     RTFUZZCTXMUTATOR_INVALID = 0,
    133     /** Flips a single bit in the input. */
    134     RTFUZZCTXMUTATOR_BIT_FLIP,
    135     /** Replaces a single byte in the input. */
    136     RTFUZZCTXMUTATOR_BYTE_REPLACE,
    137     /** Inserts a byte sequence into the input. */
    138     RTFUZZCTXMUTATOR_BYTE_SEQUENCE_INSERT,
    139     /** Appends a byte sequence to the input. */
    140     RTFUZZCTXMUTATOR_BYTE_SEQUENCE_APPEND,
    141     /** Deletes a single byte from the input. */
    142     RTFUZZCTXMUTATOR_BYTE_DELETE,
    143     /** Deletes a sequence of bytes from the input. */
    144     RTFUZZCTXMUTATOR_BYTE_SEQUENCE_DELETE,
    145     /** Last valid mutator. */
    146     RTFUZZCTXMUTATOR_LAST = RTFUZZCTXMUTATOR_BYTE_SEQUENCE_DELETE,
    147     /** 32bit hack. */
    148     RTFUZZCTXMUTATOR_32BIT_HACK = 0x7fffffff
    149 } RTFUZZCTXMUTATOR;
    150 /** Pointer to a mutator enum. */
    151 typedef RTFUZZCTXMUTATOR *PRTFUZZCTXMUTATOR;
    152235
    153236
     
    173256
    174257/**
    175  * Mutator callback.
    176  *
    177  * @returns IPRT status code.
    178  * @param   pThis               The fuzzer context instance.
    179  * @param   pvBuf               The input buffer to mutate.
    180  * @param   cbBuf               Size of the buffer in bytes.
    181  * @param   ppInputMutated      Where to store the pointer to the mutated input success.
    182  */
    183 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOR(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated);
    184 /** Pointer to a mutator callback. */
    185 typedef FNRTFUZZCTXMUTATOR *PFNRTFUZZCTXMUTATOR;
     258 * Fuzzing context memory header.
     259 */
     260typedef struct RTFUZZMEMHDR
     261{
     262    /** Size of the memory area following. */
     263    size_t                      cb;
     264#if HC_ARCH_BITS == 32
     265    /** Some padding. */
     266    uint32_t                    uPadding0;
     267#elif HC_ARCH_BITS == 64
     268#else
     269    /** Some padding. */
     270    uint64_t                    uPadding0;
     271# error "Port me"
     272#endif
     273} RTFUZZMEMHDR;
     274/** Pointer to a memory header. */
     275typedef RTFUZZMEMHDR *PRTFUZZMEMHDR;
     276
    186277
    187278
     
    189280*   Internal Functions                                                                                                           *
    190281*********************************************************************************************************************************/
    191 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
    192                                                  PPRTFUZZINPUTINT ppInputMutated);
    193 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
    194                                                      PPRTFUZZINPUTINT ppInputMutated);
    195 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
    196                                                             PPRTFUZZINPUTINT ppInputMutated);
    197 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
    198                                                             PPRTFUZZINPUTINT ppInputMutated);
    199 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
    200                                                     PPRTFUZZINPUTINT ppInputMutated);
    201 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
    202                                                             PPRTFUZZINPUTINT ppInputMutated);
    203 
     282static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     283                                                     PPRTFUZZMUTATION ppMutation);
     284static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     285                                                         PPRTFUZZMUTATION ppMutation);
     286static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     287                                                                      PPRTFUZZMUTATION ppMutation);
     288static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     289                                                        PPRTFUZZMUTATION ppMutation);
     290static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     291                                                                PPRTFUZZMUTATION ppMutation);
     292
     293static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     294                                                    uint8_t *pbBuf, size_t cbBuf);
     295static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     296                                                     uint8_t *pbBuf, size_t cbBuf);
     297static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     298                                                         uint8_t *pbBuf, size_t cbBuf);
     299static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     300                                                                      uint8_t *pbBuf, size_t cbBuf);
     301static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     302                                                        uint8_t *pbBuf, size_t cbBuf);
     303static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     304                                                                uint8_t *pbBuf, size_t cbBuf);
    204305
    205306/*********************************************************************************************************************************
     
    207308*********************************************************************************************************************************/
    208309/**
     310 * The special corpus mutator for the original data.
     311 */
     312static RTFUZZMUTATOR const g_MutatorCorpus =
     313{
     314    /** pszId */
     315    "Corpus",
     316    /** pszDesc */
     317    "Special mutator, which is assigned to the initial corpus",
     318    /** fFlags */
     319    RTFUZZMUTATOR_F_DEFAULT,
     320    /** pfnPrep */
     321    NULL,
     322    /** pfnExec */
     323    rtFuzzCtxMutatorCorpusExec
     324};
     325
     326/**
    209327 * Array of all available mutators.
    210328 */
    211 static PFNRTFUZZCTXMUTATOR const g_apfnMutators[] =
    212 {
    213     NULL,
    214     rtFuzzCtxMutatorBitFlip,
    215     rtFuzzCtxMutatorByteReplace,
    216     rtFuzzCtxMutatorByteSequenceInsert,
    217     rtFuzzCtxMutatorByteSequenceAppend,
    218     rtFuzzCtxMutatorByteDelete,
    219     rtFuzzCtxMutatorByteSequenceDelete,
    220     NULL
     329static RTFUZZMUTATOR const g_aMutators[] =
     330{
     331    /* pszId         pszDesc                                          fFlags                      pfnPrep                                       pfnExec */
     332    { "BitFlip",     "Flips a single bit in the input",               RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorBitFlipPrep,                  rtFuzzCtxMutatorBitFlipExec},
     333    { "ByteReplace", "Replaces a single byte in the input",           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteReplacePrep,              rtFuzzCtxMutatorByteReplaceExec},
     334    { "ByteSeqIns",  "Inserts a byte sequence in the input",          RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec},
     335    { "ByteSeqApp",  "Appends a byte sequence to the input",          RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec},
     336    { "ByteDelete",  "Deletes a single byte sequence from the input", RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteDeletePrep,               rtFuzzCtxMutatorByteDeleteExec},
     337    { "ByteSeqDel",  "Deletes a byte sequence from the input",        RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceDeletePrep,       rtFuzzCtxMutatorByteSequenceDeleteExec}
    221338};
    222339
    223340
    224 
    225 /**
    226  * Tries to locate an input seed with the given input MD5 seed.
    227  *
    228  * @returns Pointer to the input seed on success or NULL if not found.
     341/**
     342 * Allocates the given number of bytes.
     343 *
     344 * @returns Pointer to the allocated memory
    229345 * @param   pThis               The fuzzer context instance.
    230  * @param   pbMd5Hash           The MD5 hash to search for.
    231  * @param   fExact              Flag whether to search for an exact match or return the next best fit if no match exists.
    232  * @param   ppIntermediate      Where to store the pointer to the intermediate layer upon success, optional.
    233  */
    234 static PRTFUZZINPUTINT rtFuzzCtxInputLocate(PRTFUZZCTXINT pThis, uint8_t *pbMd5Hash, bool fExact, PPRTFUZZINTERMEDIATE ppIntermediate)
    235 {
    236     PRTFUZZINPUTINT pInput = NULL;
    237     uint64_t u64Md5High = *(uint64_t *)&pbMd5Hash[RTMD5_HASH_SIZE / 2];
    238     uint64_t u64Md5Low = *(uint64_t *)&pbMd5Hash[0];
    239     PRTFUZZINTERMEDIATE pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64Get(&pThis->TreeSeedsHigh, u64Md5High);
    240     if (!fExact && !pIntermediate)
    241         pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64GetBestFit(&pThis->TreeSeedsHigh, u64Md5High, true /*fAbove*/);
    242     if (!fExact && !pIntermediate)
    243         pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64GetBestFit(&pThis->TreeSeedsHigh, u64Md5High, false /*fAbove*/);
    244 
    245     if (pIntermediate)
    246     {
    247         /* 2nd level lookup. */
    248         pInput = (PRTFUZZINPUTINT)RTAvlU64Get(&pIntermediate->TreeSeedsLow, u64Md5Low);
    249         if (!fExact && !pInput)
    250             pInput = (PRTFUZZINPUTINT)RTAvlU64GetBestFit(&pIntermediate->TreeSeedsLow, u64Md5Low, true /*fAbove*/);
    251         if (!fExact && !pInput)
    252             pInput = (PRTFUZZINPUTINT)RTAvlU64GetBestFit(&pIntermediate->TreeSeedsLow, u64Md5Low, false /*fAbove*/);
    253     }
    254 
    255     if (ppIntermediate)
    256         *ppIntermediate = pIntermediate;
    257 
    258     return pInput;
    259 }
    260 
    261 
    262 /**
    263  * Adds the given input to the corpus of the given fuzzer context.
     346 * @param   cb                  How much to allocate.
     347 */
     348static void *rtFuzzCtxMemoryAlloc(PRTFUZZCTXINT pThis, size_t cb)
     349{
     350    PRTFUZZMEMHDR pMemHdr = (PRTFUZZMEMHDR)RTMemAllocZ(cb + sizeof(RTFUZZMEMHDR));
     351    if (RT_LIKELY(pMemHdr))
     352    {
     353        size_t cbIgn = 0;
     354        pMemHdr->cb = cb;
     355        ASMAtomicAddSize(&pThis->cbMemTotal, cb + sizeof(RTFUZZMEMHDR), &cbIgn); RT_NOREF(cbIgn);
     356        return pMemHdr + 1;
     357    }
     358
     359    return NULL;
     360}
     361
     362
     363/**
     364 * Frees the given memory.
     365 *
     366 * @returns nothing.
     367 * @param   pThis               The fuzzer context instance.
     368 * @param   pv                  Pointer to the memory area to free.
     369 */
     370static void rtFuzzCtxMemoryFree(PRTFUZZCTXINT pThis, void *pv)
     371{
     372    PRTFUZZMEMHDR pMemHdr = ((PRTFUZZMEMHDR)pv) - 1;
     373
     374    size_t cbIgn = 0;
     375    ASMAtomicSubSize(&pThis->cbMemTotal, pMemHdr->cb + sizeof(RTFUZZMEMHDR), &cbIgn); RT_NOREF(cbIgn);
     376    RTMemFree(pMemHdr);
     377}
     378
     379
     380/**
     381 * Retains an external reference to the given mutation.
     382 *
     383 * @returns New reference count on success.
     384 * @param   pMutation           The mutation to retain.
     385 */
     386static uint32_t rtFuzzMutationRetain(PRTFUZZMUTATION pMutation)
     387{
     388    uint32_t cRefs = ASMAtomicIncU32(&pMutation->cRefs);
     389    AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
     390    return cRefs;
     391}
     392
     393#if 0 /* unused */
     394/**
     395 * Releases an external reference from the given mutation.
     396 *
     397 * @returns New reference count on success.
     398 * @param   pMutation           The mutation to retain.
     399 */
     400static uint32_t rtFuzzMutationRelease(PRTFUZZMUTATION pMutation)
     401{
     402    uint32_t cRefs = ASMAtomicDecU32(&pMutation->cRefs);
     403    AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
     404    return cRefs;
     405}
     406#endif
     407
     408/**
     409 * Adds the given mutation to the corpus of the given fuzzer context.
    264410 *
    265411 * @returns IPRT status code.
    266412 * @param   pThis               The fuzzer context instance.
    267  * @param   pInput              The input to add.
    268  */
    269 static int rtFuzzCtxInputAdd(PRTFUZZCTXINT pThis, PRTFUZZINPUTINT pInput)
     413 * @param   pMutation           The mutation to add.
     414 */
     415static int rtFuzzCtxMutationAdd(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation)
    270416{
    271417    int rc = VINF_SUCCESS;
    272     uint64_t u64Md5High = *(uint64_t *)&pInput->abMd5Hash[RTMD5_HASH_SIZE / 2];
    273     uint64_t u64Md5Low = *(uint64_t *)&pInput->abMd5Hash[0];
    274 
    275     pInput->Core.Key = u64Md5Low;
    276     PRTFUZZINTERMEDIATE pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64Get(&pThis->TreeSeedsHigh, u64Md5High);
    277     if (!pIntermediate)
    278     {
    279         pIntermediate = (PRTFUZZINTERMEDIATE)RTMemAllocZ(sizeof(*pIntermediate));
    280         if (RT_LIKELY(pIntermediate))
     418
     419    pMutation->Core.Key = ASMAtomicIncU64(&pThis->cMutations) - 1;
     420    rc = RTSemRWRequestWrite(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
     421    AssertRC(rc); RT_NOREF(rc);
     422    bool fIns = RTAvlU64Insert(&pThis->TreeMutations, &pMutation->Core);
     423    Assert(fIns);
     424    rc = RTSemRWReleaseWrite(pThis->hSemRwMutations);
     425    AssertRC(rc); RT_NOREF(rc);
     426
     427    return rc;
     428}
     429
     430
     431/**
     432 * Returns a random mutation from the corpus of the given fuzzer context.
     433 *
     434 * @returns Pointer to a randomly picked mutation (reference count is increased).
     435 * @param   pThis               The fuzzer context instance.
     436 */
     437static PRTFUZZMUTATION rtFuzzCtxMutationPickRnd(PRTFUZZCTXINT pThis)
     438{
     439    uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 0, ASMAtomicReadU64(&pThis->cMutations));
     440
     441    int rc = RTSemRWRequestRead(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
     442    AssertRC(rc); RT_NOREF(rc);
     443
     444    /*
     445     * Using best fit getter here as there might be a racing mutation insertion and the mutation counter has increased
     446     * already but the mutation is not yet in the tree.
     447     */
     448    PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)RTAvlU64GetBestFit(&pThis->TreeMutations, idxMutation, false /*fAbove*/);
     449    AssertPtr(pMutation);
     450
     451    /* Increase reference count of the mutation. */
     452    rtFuzzMutationRetain(pMutation);
     453    rc = RTSemRWReleaseRead(pThis->hSemRwMutations);
     454    AssertRC(rc); RT_NOREF(rc);
     455
     456    return pMutation;
     457}
     458
     459
     460/**
     461 * Creates a new mutation capable of holding the additional number of bytes.
     462 *
     463 * @returns Pointer to the newly created mutation or NULL if out of memory.
     464 * @param   pThis               The fuzzer context instance.
     465 * @param   offMutation         The starting offset for the mutation.
     466 * @param   pMutationParent     The parent mutation, can be NULL.
     467 * @param   cbAdditional        Additional number of bytes to allocate after the core structure.
     468 */
     469static PRTFUZZMUTATION rtFuzzMutationCreate(PRTFUZZCTXINT pThis, uint64_t offMutation, PRTFUZZMUTATION pMutationParent, size_t cbAdditional)
     470{
     471    PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)rtFuzzCtxMemoryAlloc(pThis, sizeof(RTFUZZMUTATION) + cbAdditional);
     472    if (RT_LIKELY(pMutation))
     473    {
     474        pMutation->u32Magic        = 0; /** @todo */
     475        pMutation->pFuzzer         = pThis;
     476        pMutation->cRefs           = 1;
     477        pMutation->iLvl            = 0;
     478        pMutation->offMutation     = offMutation;
     479        pMutation->pMutationParent = pMutationParent;
     480
     481        if (pMutationParent)
     482            pMutation->iLvl = pMutationParent->iLvl + 1;
     483    }
     484
     485    return pMutation;
     486}
     487
     488
     489/**
     490 * Destroys the given mutation.
     491 *
     492 * @returns nothing.
     493 * @param   pMutation           The mutation to destroy.
     494 */
     495static void rtFuzzMutationDestroy(PRTFUZZMUTATION pMutation)
     496{
     497    rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation);
     498}
     499
     500
     501/**
     502 * Destorys the given fuzzer context freeing all allocated resources.
     503 *
     504 * @returns nothing.
     505 * @param   pThis               The fuzzer context instance.
     506 */
     507static void rtFuzzCtxDestroy(PRTFUZZCTXINT pThis)
     508{
     509    RT_NOREF(pThis);
     510}
     511
     512
     513static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     514                                                    uint8_t *pbBuf, size_t cbBuf)
     515{
     516    RT_NOREF(pThis, cbBuf);
     517    memcpy(pbBuf, &pMutation->u.abCorpus[0], pMutation->cbInput);
     518    return VINF_SUCCESS;
     519}
     520
     521
     522/**
     523 * Mutator callback - flips a single bit in the input.
     524 */
     525static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     526                                                     PPRTFUZZMUTATION ppMutation)
     527{
     528    int rc = VINF_SUCCESS;
     529    PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     530    if (RT_LIKELY(pMutation))
     531    {
     532        pMutation->cbInput      = pMutationParent->cbInput; /* Bit flips don't change the input size. */
     533        pMutation->u.idxBitFlip = RTRandAdvS32Ex(pThis->hRand, 0, (pMutationParent->cbInput - offStart) * 8 - 1);
     534        *ppMutation = pMutation;
     535    }
     536    else
     537        rc = VERR_NO_MEMORY;
     538
     539    return rc;
     540}
     541
     542
     543static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     544                                                     uint8_t *pbBuf, size_t cbBuf)
     545{
     546    RT_NOREF(pThis, cbBuf);
     547    ASMBitToggle(pbBuf, pMutation->u.idxBitFlip);
     548    return VINF_SUCCESS;
     549}
     550
     551
     552/**
     553 * Mutator callback - replaces a single byte in the input.
     554 */
     555static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     556                                                         PPRTFUZZMUTATION ppMutation)
     557{
     558    int rc = VINF_SUCCESS;
     559    PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     560    if (RT_LIKELY(pMutation))
     561    {
     562        pMutation->cbInput = pMutationParent->cbInput; /* Byte replacements don't change the input size. */
     563        RTRandAdvBytes(pThis->hRand, &pMutation->u.bByteReplace, 1); /** @todo: Filter out same values. */
     564        *ppMutation = pMutation;
     565    }
     566    else
     567        rc = VERR_NO_MEMORY;
     568
     569    return rc;
     570}
     571
     572
     573static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     574                                                         uint8_t *pbBuf, size_t cbBuf)
     575{
     576    RT_NOREF(pThis, cbBuf);
     577    *pbBuf = pMutation->u.bByteReplace;
     578    return VINF_SUCCESS;
     579}
     580
     581
     582/**
     583 * Mutator callback - inserts a byte sequence into the input.
     584 */
     585static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     586                                                                      PPRTFUZZMUTATION ppMutation)
     587{
     588    int rc = VINF_SUCCESS;
     589    if (pMutationParent->cbInput < pThis->cbInputMax)
     590    {
     591        size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, pMutationParent->cbInput + 1, pThis->cbInputMax);
     592        size_t cbInsert = cbInputMutated - pMutationParent->cbInput;
     593
     594        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, cbInsert);
     595        if (RT_LIKELY(pMutation))
    281596        {
    282             pIntermediate->Core.Key = u64Md5High;
    283             pIntermediate->TreeSeedsLow = NULL;
    284             bool fIns = RTAvlU64Insert(&pThis->TreeSeedsHigh, &pIntermediate->Core);
    285             Assert(fIns); RT_NOREF(fIns);
     597            pMutation->cbInput = cbInputMutated;
     598            RTRandAdvBytes(pThis->hRand, &pMutation->u.abAdd[0], cbInsert);
     599            *ppMutation = pMutation;
    286600        }
    287601        else
     
    289603    }
    290604
    291     if (RT_SUCCESS(rc))
    292     {
    293         AssertPtr(pIntermediate);
    294         bool fIns = RTAvlU64Insert(&pIntermediate->TreeSeedsLow, &pInput->Core);
    295         if (!fIns)
    296             rc = VERR_ALREADY_EXISTS;
    297         else
     605    return rc;
     606}
     607
     608
     609static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     610                                                                      uint8_t *pbBuf, size_t cbBuf)
     611{
     612    RT_NOREF(pThis);
     613    size_t cbInsert = pMutation->cbInput - pMutation->pMutationParent->cbInput;
     614
     615    /* Move any remaining data to the end. */
     616    if (cbBuf)
     617        memmove(pbBuf + cbInsert, pbBuf, cbBuf);
     618
     619    memcpy(pbBuf, &pMutation->u.abAdd[0], cbInsert);
     620    return VINF_SUCCESS;
     621}
     622
     623
     624/**
     625 * Mutator callback - deletes a single byte in the input.
     626 */
     627static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     628                                                        PPRTFUZZMUTATION ppMutation)
     629{
     630    int rc = VINF_SUCCESS;
     631    if (pMutationParent->cbInput - offStart >= 1)
     632    {
     633        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     634        if (RT_LIKELY(pMutation))
    298635        {
    299             RTListAppend(&pThis->LstInputs, &pInput->NdInputs);
    300             pThis->cInputs++;
    301             RTFuzzInputRetain(pInput);
    302         }
    303     }
    304 
    305     return rc;
    306 }
    307 
    308 
    309 /**
    310  * Returns a random input from the corpus of the given fuzzer context.
    311  *
    312  * @returns Pointer to a randomly picked input.
    313  * @param   pThis               The fuzzer context instance.
    314  */
    315 static PRTFUZZINPUTINT rtFuzzCtxInputPickRnd(PRTFUZZCTXINT pThis)
    316 {
    317     /* Generate a random MD5 hash and do a non exact localisation. */
    318     uint8_t abDigestRnd[RTMD5_HASH_SIZE];
    319     RTRandAdvBytes(pThis->hRand, &abDigestRnd[0], sizeof(abDigestRnd));
    320 
    321     return rtFuzzCtxInputLocate(pThis, &abDigestRnd[0], false /*fExact*/, NULL /*ppIntermediate*/);
    322 }
    323 
    324 
    325 /**
    326  * Clones a given input.
    327  *
    328  * @returns Pointer to the cloned input or NULL if out of memory.
    329  * @param   pThis               The fuzzer context instance.
    330  * @param   pvBuf               The buffer to clone.
    331  * @param   cbBuf               Size of the buffer in bytes.
    332  */
    333 static PRTFUZZINPUTINT rtFuzzCtxInputClone(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf)
    334 {
    335     PRTFUZZINPUTINT pInpClone = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbBuf]));
    336     if (RT_LIKELY(pInpClone))
    337     {
    338         pInpClone->cRefs    = 1;
    339         pInpClone->pFuzzer  = pThis,
    340         pInpClone->cbInput  = cbBuf;
    341         memcpy(&pInpClone->abInput[0], pvBuf, cbBuf);
    342     }
    343 
    344     return pInpClone;
    345 }
    346 
    347 
    348 /**
    349  * Creates an empty input seed capable of holding the given number of bytes.
    350  *
    351  * @returns Pointer to the newly created input seed.
    352  * @param   pThis               The fuzzer context instance.
    353  * @param   cbInput             Input seed size in bytes.
    354  */
    355 static PRTFUZZINPUTINT rtFuzzCtxInputCreate(PRTFUZZCTXINT pThis, size_t cbInput)
    356 {
    357     PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbInput]));
    358     if (RT_LIKELY(pInput))
    359     {
    360         pInput->pFuzzer = pThis;
    361         pInput->cRefs   = 1;
    362         pInput->cbInput = cbInput;
    363     }
    364 
    365     return pInput;
    366 }
    367 
    368 
    369 /**
    370  * Destroys the given input.
    371  *
    372  * @returns nothing.
    373  * @param   pInput              The input to destroy.
    374  */
    375 static void rtFuzzInputDestroy(PRTFUZZINPUTINT pInput)
    376 {
    377     RTMemFree(pInput);
    378 }
    379 
    380 
    381 /**
    382  * Destorys the given fuzzer context freeing all allocated resources.
    383  *
    384  * @returns nothing.
    385  * @param   pThis               The fuzzer context instance.
    386  */
    387 static void rtFuzzCtxDestroy(PRTFUZZCTXINT pThis)
    388 {
    389     RT_NOREF(pThis);
    390 }
    391 
    392 
    393 /**
    394  * Mutator callback - flips a single bit in the input.
    395  */
    396 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    397 {
    398     int rc = VINF_SUCCESS;
    399     PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf);
    400     if (RT_LIKELY(pInputMutated))
    401     {
    402         int32_t iBit = RTRandAdvS32Ex(pThis->hRand, 0, (uint32_t)cbBuf * 8 - 1);
    403         ASMBitToggle(&pInputMutated->abInput[0], iBit);
    404         RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    405         *ppInputMutated = pInputMutated;
    406     }
    407     else
    408         rc = VERR_NO_MEMORY;
    409 
    410     return rc;
    411 }
    412 
    413 
    414 /**
    415  * Mutator callback - replaces a single byte in the input.
    416  */
    417 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    418 {
    419     int rc = VINF_SUCCESS;
    420     PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf);
    421     if (RT_LIKELY(pInputMutated))
    422     {
    423         uint8_t *pbBuf = (uint8_t *)pvBuf;
    424         uint32_t offByte = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1);
    425         RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offByte], 1);
    426         if (pbBuf[offByte] != pInputMutated->abInput[offByte])
    427         {
    428             RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    429             *ppInputMutated = pInputMutated;
    430         }
    431         else
    432             RTMemFree(pInputMutated);
    433     }
    434     else
    435         rc = VERR_NO_MEMORY;
    436 
    437     return rc;
    438 }
    439 
    440 
    441 /**
    442  * Mutator callback - inserts a byte sequence into the input.
    443  */
    444 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    445 {
    446     int rc = VINF_SUCCESS;
    447     if (cbBuf < pThis->cbInputMax)
    448     {
    449         size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, (uint32_t)cbBuf + 1, (uint32_t)pThis->cbInputMax);
    450         size_t cbInsert = cbInputMutated - cbBuf;
    451         uint32_t offInsert = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf);
    452         uint8_t *pbBuf = (uint8_t *)pvBuf;
    453         PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated);
    454         if (RT_LIKELY(pInputMutated))
    455         {
    456             if (offInsert)
    457                 memcpy(&pInputMutated->abInput[0], pbBuf, offInsert);
    458             RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offInsert], cbInsert);
    459             memcpy(&pInputMutated->abInput[offInsert + cbInsert], &pbBuf[offInsert], cbBuf - offInsert);
    460             RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    461             *ppInputMutated = pInputMutated;
     636            pMutation->cbInput = pMutationParent->cbInput - 1;
     637            *ppMutation = pMutation;
    462638        }
    463639        else
     
    469645
    470646
    471 /**
    472  * Mutator callback - appends a byte sequence to the input.
    473  */
    474 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
     647static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     648                                                        uint8_t *pbBuf, size_t cbBuf)
     649{
     650    RT_NOREF(pThis, pMutation);
     651
     652    /* Just move the residual data to the front. */
     653    memmove(pbBuf, pbBuf + 1, cbBuf - 1);
     654    return VINF_SUCCESS;
     655}
     656
     657
     658
     659/**
     660 * Mutator callback - deletes a byte sequence in the input.
     661 */
     662static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     663                                                                PPRTFUZZMUTATION ppMutation)
    475664{
    476665    int rc = VINF_SUCCESS;
    477     if (cbBuf < pThis->cbInputMax)
    478     {
    479         size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, (uint32_t)cbBuf + 1, (uint32_t)pThis->cbInputMax);
    480         size_t cbInsert = cbInputMutated - cbBuf;
    481         PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated);
    482         if (RT_LIKELY(pInputMutated))
     666    if (pMutationParent->cbInput > 1)
     667    {
     668        size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, offStart, pMutationParent->cbInput - 1);
     669
     670        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     671        if (RT_LIKELY(pMutation))
    483672        {
    484             memcpy(&pInputMutated->abInput[0], pvBuf, cbBuf);
    485             RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[cbBuf], cbInsert);
    486             RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    487             *ppInputMutated = pInputMutated;
     673            pMutation->cbInput = cbInputMutated;
     674            *ppMutation = pMutation;
    488675        }
    489676        else
     
    495682
    496683
    497 /**
    498  * Mutator callback - deletes a single byte in the input.
    499  */
    500 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    501 {
    502     int rc = VINF_SUCCESS;
    503     if (cbBuf > 1)
    504     {
    505         uint32_t offDelete = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1);
    506         uint8_t *pbBuf = (uint8_t *)pvBuf;
    507         PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbBuf - 1);
    508         if (RT_LIKELY(pInputMutated))
     684static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     685                                                                uint8_t *pbBuf, size_t cbBuf)
     686{
     687    RT_NOREF(pThis);
     688    Assert(pMutation->pMutationParent->cbInput > pMutation->cbInput);
     689    size_t cbDel = pMutation->pMutationParent->cbInput - pMutation->cbInput;
     690
     691    /* Just move the residual data to the front. */
     692    memmove(pbBuf, pbBuf + cbDel, cbBuf - cbDel);
     693    return VINF_SUCCESS;
     694}
     695
     696
     697/**
     698 * Creates an empty fuzzing context.
     699 *
     700 * @returns IPRT status code.
     701 * @param   ppThis              Where to store the pointer to the internal fuzzing context instance on success.
     702 * @param   enmType             Fuzzing context type.
     703 */
     704static int rtFuzzCtxCreateEmpty(PRTFUZZCTXINT *ppThis, RTFUZZCTXTYPE enmType)
     705{
     706    int rc;
     707    PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis));
     708    if (RT_LIKELY(pThis))
     709    {
     710        pThis->u32Magic         = RTFUZZCTX_MAGIC;
     711        pThis->cRefs            = 1;
     712        pThis->enmType          = enmType;
     713        pThis->TreeMutations    = NULL;
     714        pThis->cbInputMax       = UINT32_MAX;
     715        pThis->cMutations       = 0;
     716        pThis->fFlagsBehavioral = 0;
     717        pThis->cbMemTotal       = 0;
     718
     719        /* Copy the default mutator descriptors over. */
     720        pThis->paMutators = (PRTFUZZMUTATOR)RTMemAllocZ(RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR));
     721        if (RT_LIKELY(pThis->paMutators))
    509722        {
    510             if (offDelete)
    511                 memcpy(&pInputMutated->abInput[0], pbBuf, offDelete);
    512             if (offDelete < cbBuf - 1)
    513                 memcpy(&pInputMutated->abInput[offDelete], &pbBuf[offDelete + 1], cbBuf - offDelete - 1);
    514             RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    515             *ppInputMutated = pInputMutated;
     723            pThis->cMutators = RT_ELEMENTS(g_aMutators);
     724            memcpy(&pThis->paMutators[0], &g_aMutators[0], RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR));
     725
     726            rc = RTSemRWCreate(&pThis->hSemRwMutations);
     727            if (RT_SUCCESS(rc))
     728            {
     729                rc = RTRandAdvCreateParkMiller(&pThis->hRand);
     730                if (RT_SUCCESS(rc))
     731                {
     732                    RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS());
     733                    *ppThis = pThis;
     734                    return VINF_SUCCESS;
     735                }
     736
     737                RTSemRWDestroy(pThis->hSemRwMutations);
     738            }
    516739        }
    517740        else
    518741            rc = VERR_NO_MEMORY;
    519     }
    520 
    521     return rc;
    522 }
    523 
    524 
    525 /**
    526  * Mutator callback - deletes a byte sequence in the input.
    527  */
    528 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    529 {
    530     int rc = VINF_SUCCESS;
    531     if (cbBuf > 1)
    532     {
    533         size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1);
    534         size_t cbDel = cbBuf - cbInputMutated;
    535         uint32_t offDel = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)(cbBuf - cbDel));
    536         uint8_t *pbBuf = (uint8_t *)pvBuf;
    537 
    538         PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated);
    539         if (RT_LIKELY(pInputMutated))
    540         {
    541             if (offDel)
    542                 memcpy(&pInputMutated->abInput[0], pbBuf, offDel);
    543             memcpy(&pInputMutated->abInput[offDel], &pbBuf[offDel + cbDel], cbBuf - offDel - cbDel);
    544             RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    545             *ppInputMutated = pInputMutated;
    546         }
    547         else
    548             rc = VERR_NO_MEMORY;
    549     }
    550 
    551     return rc;
    552 }
    553 
    554 
    555 static PRTFUZZCTXINT rtFuzzCtxCreateEmpty(void)
    556 {
    557     PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis));
    558     if (RT_LIKELY(pThis))
    559     {
    560         pThis->u32Magic         = RTFUZZCTX_MAGIC;
    561         pThis->cRefs            = 1;
    562         pThis->TreeSeedsHigh    = NULL;
    563         pThis->cbInputMax       = UINT32_MAX;
    564         pThis->cInputs          = 0;
    565         pThis->fFlagsBehavioral = 0;
    566         RTListInit(&pThis->LstInputs);
    567 
    568         int rc = RTRandAdvCreateParkMiller(&pThis->hRand);
    569         if (RT_SUCCESS(rc))
    570         {
    571             RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS());
    572             return pThis;
    573         }
    574742
    575743        RTMemFree(pThis);
    576     }
    577 
    578     return NULL;
    579 }
    580 
    581 
    582 RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx)
    583 {
    584     AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
    585 
    586     int rc = VINF_SUCCESS;
    587     PRTFUZZCTXINT pThis = rtFuzzCtxCreateEmpty();
    588     if (RT_LIKELY(pThis))
    589     {
    590         *phFuzzCtx = pThis;
    591         return VINF_SUCCESS;
    592744    }
    593745    else
     
    595747
    596748    return rc;
     749}
     750
     751
     752/**
     753 * Destroys the given fuzzing input.
     754 *
     755 * @returns nothing.
     756 * @param   pThis               The fuzzing input to destroy.
     757 */
     758static void rtFuzzInputDestroy(PRTFUZZINPUTINT pThis)
     759{
     760    PRTFUZZCTXINT pFuzzer = pThis->pFuzzer;
     761
     762    if (   pFuzzer->enmType == RTFUZZCTXTYPE_BLOB
     763        && pThis->u.Blob.pvInput)
     764        rtFuzzCtxMemoryFree(pFuzzer, pThis->u.Blob.pvInput);
     765
     766    rtFuzzCtxMemoryFree(pFuzzer, pThis);
     767    RTFuzzCtxRelease(pFuzzer);
     768}
     769
     770
     771/**
     772 * Creates the final input data applying all accumulated mutations.
     773 *
     774 * @returns IPRT status code.
     775 * @param   pThis               The fuzzing input to finalize.
     776 */
     777static int rtFuzzInputDataFinalize(PRTFUZZINPUTINT pThis)
     778{
     779    Assert(!pThis->u.Blob.pvInput);
     780
     781    int rc = VINF_SUCCESS;
     782    uint8_t *pbBuf = (uint8_t *)rtFuzzCtxMemoryAlloc(pThis->pFuzzer, pThis->u.Blob.cbAlloc);
     783    if (RT_LIKELY(pbBuf))
     784    {
     785        pThis->u.Blob.pvInput = pbBuf;
     786        pThis->u.Blob.cbInput = pThis->pMutationTop->cbInput;
     787
     788        size_t cbInputNow = pThis->apMutations[0]->cbInput;
     789        for (uint32_t i = 0; i < pThis->pMutationTop->iLvl + 1; i++)
     790        {
     791            PCRTFUZZMUTATION pMutation = pThis->apMutations[i];
     792            pMutation->pMutator->pfnExec(pThis->pFuzzer, pMutation, pbBuf + pMutation->offMutation,
     793                                         cbInputNow - pMutation->offMutation);
     794
     795            cbInputNow = pMutation->cbInput;
     796        }
     797
     798        Assert(cbInputNow == pThis->u.Blob.cbInput);
     799    }
     800    else
     801        rc = VERR_NO_MEMORY;
     802
     803    return rc;
     804}
     805
     806
     807RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx, RTFUZZCTXTYPE enmType)
     808{
     809    AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
     810
     811    return rtFuzzCtxCreateEmpty(phFuzzCtx, enmType);
    597812}
    598813
     
    604819    AssertReturn(cbState > 0, VERR_INVALID_PARAMETER);
    605820
     821#if 0
    606822    int rc = VINF_SUCCESS;
    607823    if (cbState >= sizeof(RTFUZZCTXSTATE))
     
    679895
    680896    return rc;
     897#else
     898    return VERR_NOT_IMPLEMENTED;
     899#endif
    681900}
    682901
     
    734953    AssertPtrReturn(pcbState, VERR_INVALID_POINTER);
    735954
     955#if 0
    736956    char aszPrngExport[_4K]; /* Should be plenty of room here. */
    737957    size_t cbPrng = sizeof(aszPrngExport);
     
    7991019
    8001020    return rc;
     1021#else
     1022    return VERR_NOT_IMPLEMENTED;
     1023#endif
    8011024}
    8021025
     
    8381061    AssertReturn(cbInput, VERR_INVALID_POINTER);
    8391062
    840     /* Generate MD5 checksum and try to locate input. */
    8411063    int rc = VINF_SUCCESS;
    842     uint8_t abDigest[RTMD5_HASH_SIZE];
    843     RTMd5(pvInput, cbInput, &abDigest[0]);
    844 
    845     PRTFUZZINPUTINT pInput = rtFuzzCtxInputLocate(pThis, &abDigest[0], true /*fExact*/, NULL /*ppIntermediate*/);
    846     if (!pInput)
    847     {
    848         pInput = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbInput]));
    849         if (RT_LIKELY(pInput))
    850         {
    851             pInput->cRefs   = 1;
    852             pInput->pFuzzer = pThis;
    853             pInput->cbInput = cbInput;
    854             memcpy(&pInput->abInput[0], pvInput, cbInput);
    855             memcpy(&pInput->abMd5Hash[0], &abDigest[0], sizeof(abDigest));
    856             rc = rtFuzzCtxInputAdd(pThis, pInput);
    857             if (RT_FAILURE(rc))
    858                 RTMemFree(pInput);
    859         }
    860         else
    861             rc = VERR_NO_MEMORY;
     1064    PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbInput);
     1065    if (RT_LIKELY(pMutation))
     1066    {
     1067        pMutation->pMutator = &g_MutatorCorpus;
     1068        pMutation->cbInput  = cbInput;
     1069        memcpy(&pMutation->u.abCorpus[0], pvInput, cbInput);
     1070        rc = rtFuzzCtxMutationAdd(pThis, pMutation);
     1071        if (RT_FAILURE(rc))
     1072            rtFuzzMutationDestroy(pMutation);
    8621073    }
    8631074    else
    864         rc = VERR_ALREADY_EXISTS;
     1075        rc = VERR_NO_MEMORY;
    8651076
    8661077    return rc;
     
    8971108    if (RT_SUCCESS(rc))
    8981109    {
    899         PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbFile]));
    900         if (RT_LIKELY(pInput))
     1110        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbFile);
     1111        if (RT_LIKELY(pMutation))
    9011112        {
    902             pInput->cRefs   = 1;
    903             pInput->pFuzzer = pThis;
    904             pInput->cbInput = cbFile;
    905 
    906             rc = RTVfsFileRead(hVfsFile, &pInput->abInput[0], cbFile, NULL);
     1113            pMutation->pMutator = &g_MutatorCorpus;
     1114            pMutation->cbInput  = cbFile;
     1115            rc = RTVfsFileRead(hVfsFile, &pMutation->u.abCorpus[0], cbFile, NULL);
    9071116            if (RT_SUCCESS(rc))
    908             {
    909                 /* Generate MD5 checksum and try to locate input. */
    910                 uint8_t abDigest[RTMD5_HASH_SIZE];
    911                 RTMd5(&pInput->abInput[0], cbFile, &abDigest[0]);
    912 
    913                 if (!rtFuzzCtxInputLocate(pThis, &abDigest[0], true /*fExact*/, NULL /*ppIntermediate*/))
    914                 {
    915                     memcpy(&pInput->abMd5Hash[0], &abDigest[0], sizeof(abDigest));
    916                     rc = rtFuzzCtxInputAdd(pThis, pInput);
    917                 }
    918                 else
    919                     rc = VERR_ALREADY_EXISTS;
    920             }
     1117                rc = rtFuzzCtxMutationAdd(pThis, pMutation);
    9211118
    9221119            if (RT_FAILURE(rc))
    923                 RTMemFree(pInput);
     1120                rtFuzzMutationDestroy(pMutation);
    9241121        }
    925         else
    926             rc = VERR_NO_MEMORY;
    9271122    }
    9281123
     
    10591254
    10601255    uint32_t cTries = 0;
    1061     PRTFUZZINPUTINT pSrc = rtFuzzCtxInputPickRnd(pThis);
     1256    PRTFUZZMUTATION pMutationParent = rtFuzzCtxMutationPickRnd(pThis);
    10621257    do
    10631258    {
    1064         RTFUZZCTXMUTATOR enmMutator = (RTFUZZCTXMUTATOR)RTRandAdvU32Ex(pThis->hRand, 1, RTFUZZCTXMUTATOR_LAST);
    1065         PRTFUZZINPUTINT pInput = NULL;
    1066         rc = g_apfnMutators[enmMutator](pThis, &pSrc->abInput[0], pSrc->cbInput, &pInput);
     1259        uint32_t idxMutator = RTRandAdvU32Ex(pThis->hRand, 0, pThis->cMutators - 1);
     1260        PCRTFUZZMUTATOR pMutator = &pThis->paMutators[idxMutator];
     1261        PRTFUZZMUTATION pMutation = NULL;
     1262
     1263        uint64_t offStart = 0;
     1264        if (!(pMutator->fFlags & RTFUZZMUTATOR_F_END_OF_BUF))
     1265            offStart = RTRandAdvU64Ex(pThis->hRand, 0, pMutationParent->cbInput);
     1266        else
     1267            offStart = pMutationParent->cbInput;
     1268
     1269        rc = pMutator->pfnPrep(pThis, offStart, pMutationParent, &pMutation);
    10671270        if (   RT_SUCCESS(rc)
    1068             && VALID_PTR(pInput))
     1271            && VALID_PTR(pMutation))
    10691272        {
     1273            pMutation->pMutator = pMutator;
     1274
    10701275            if (pThis->fFlagsBehavioral & RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS)
    1071                 rtFuzzCtxInputAdd(pThis, pInput);
    1072             *phFuzzInput = pInput;
    1073             return rc;
     1276                rtFuzzCtxMutationAdd(pThis, pMutation);
     1277
     1278            /* Create a new input. */
     1279            PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)rtFuzzCtxMemoryAlloc(pThis, RT_UOFFSETOF_DYN(RTFUZZINPUTINT, apMutations[pMutation->iLvl + 1]));
     1280            if (RT_LIKELY(pInput))
     1281            {
     1282                pInput->u32Magic     = 0; /** @todo */
     1283                pInput->cRefs        = 1;
     1284                pInput->pFuzzer      = pThis;
     1285                pInput->pMutationTop = pMutation;
     1286                RTFuzzCtxRetain(pThis);
     1287
     1288                /* Traverse the mutations top to bottom and insert into the array. */
     1289                uint32_t idx = pMutation->iLvl + 1;
     1290                PCRTFUZZMUTATION pMutationCur = pMutation;
     1291                size_t cbAlloc = 0;
     1292                while (idx > 0)
     1293                {
     1294                    pInput->apMutations[idx - 1] = pMutationCur;
     1295                    cbAlloc = RT_MAX(cbAlloc, pMutationCur->cbInput);
     1296                    pMutationCur = pMutationCur->pMutationParent;
     1297                    idx--;
     1298                }
     1299
     1300                pInput->u.Blob.cbAlloc = cbAlloc;
     1301                *phFuzzInput = pInput;
     1302                return rc;
     1303            }
     1304            else
     1305                rc = VERR_NO_MEMORY;
    10741306        }
    10751307    } while (++cTries <= 50);
     
    10821314
    10831315
    1084 RTDECL(int) RTFuzzCtxMutateBuffer(RTFUZZCTX hFuzzCtx, void *pvBuf, size_t cbBuf, PRTFUZZINPUT phFuzzInput)
    1085 {
     1316RTDECL(int) RTFuzzInputQueryBlobData(RTFUZZINPUT hFuzzInput, void **ppv, size_t *pcb)
     1317{
     1318    PRTFUZZINPUTINT pThis = hFuzzInput;
     1319    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1320    AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
     1321
    10861322    int rc = VINF_SUCCESS;
    1087     PRTFUZZCTXINT pThis = hFuzzCtx;
    1088     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1089     AssertPtrReturn(phFuzzInput, VERR_INVALID_POINTER);
    1090 
    1091     uint32_t cTries = 0;
    1092     do
    1093     {
    1094         RTFUZZCTXMUTATOR enmMutator = (RTFUZZCTXMUTATOR)RTRandAdvU32Ex(pThis->hRand, 1, RTFUZZCTXMUTATOR_LAST);
    1095         PRTFUZZINPUTINT pInput = NULL;
    1096         rc = g_apfnMutators[enmMutator](pThis, pvBuf, cbBuf, &pInput);
    1097         if (   RT_SUCCESS(rc)
    1098             && VALID_PTR(pInput))
    1099         {
    1100             *phFuzzInput = pInput;
    1101             return rc;
    1102         }
    1103     } while (++cTries <= 50);
     1323    if (!pThis->u.Blob.pvInput)
     1324        rc = rtFuzzInputDataFinalize(pThis);
    11041325
    11051326    if (RT_SUCCESS(rc))
    1106         rc = VERR_INVALID_STATE;
    1107 
    1108     return rc;
     1327    {
     1328        AssertPtr(pThis->u.Blob.pvInput);
     1329        Assert(pThis->u.Blob.cbInput > 0);
     1330
     1331        *ppv = pThis->u.Blob.pvInput;
     1332        *pcb = pThis->u.Blob.cbInput;
     1333    }
     1334
     1335    return rc;
     1336}
     1337
     1338
     1339RTDECL(int) RTFuzzInputMutateStreamData(RTFUZZINPUT hFuzzInput, void *pvBuf, size_t cbBuf)
     1340{
     1341    PRTFUZZINPUTINT pThis = hFuzzInput;
     1342    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1343    AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_STREAM, VERR_INVALID_STATE);
     1344
     1345    RT_NOREF(pvBuf, cbBuf);
     1346    return VERR_NOT_IMPLEMENTED;
    11091347}
    11101348
     
    11371375
    11381376
    1139 RTDECL(int) RTFuzzInputQueryData(RTFUZZINPUT hFuzzInput, void **ppv, size_t *pcb)
    1140 {
    1141     PRTFUZZINPUTINT pThis = hFuzzInput;
    1142     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1143     AssertPtrReturn(ppv, VERR_INVALID_POINTER);
    1144     AssertPtrReturn(pcb, VERR_INVALID_POINTER);
    1145 
    1146     *ppv = &pThis->abInput[0];
    1147     *pcb = pThis->cbInput;
    1148     return VINF_SUCCESS;
    1149 }
    1150 
    1151 
    11521377RTDECL(int) RTFuzzInputQueryDigestString(RTFUZZINPUT hFuzzInput, char *pszDigest, size_t cchDigest)
    11531378{
    11541379    PRTFUZZINPUTINT pThis = hFuzzInput;
    11551380    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1381    AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
    11561382    AssertPtrReturn(pszDigest, VERR_INVALID_POINTER);
    11571383    AssertReturn(cchDigest >= RTMD5_STRING_LEN + 1, VERR_INVALID_PARAMETER);
    11581384
    1159     return RTMd5ToString(&pThis->abMd5Hash[0], pszDigest, cchDigest);
     1385    int rc = VINF_SUCCESS;
     1386    if (!pThis->u.Blob.pvInput)
     1387        rc = rtFuzzInputDataFinalize(pThis);
     1388
     1389    if (RT_SUCCESS(rc))
     1390    {
     1391        uint8_t abHash[RTMD5_HASH_SIZE];
     1392        RTMd5(pThis->u.Blob.pvInput, pThis->u.Blob.cbInput, &abHash[0]);
     1393        rc = RTMd5ToString(&abHash[0], pszDigest, cchDigest);
     1394    }
     1395
     1396    return rc;
    11601397}
    11611398
     
    11651402    PRTFUZZINPUTINT pThis = hFuzzInput;
    11661403    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1404    AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
    11671405    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    11681406
    1169     RTFILE hFile;
    1170     int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     1407    int rc = VINF_SUCCESS;
     1408    if (!pThis->u.Blob.pvInput)
     1409        rc = rtFuzzInputDataFinalize(pThis);
     1410
    11711411    if (RT_SUCCESS(rc))
    11721412    {
    1173         rc = RTFileWrite(hFile, &pThis->abInput[0], pThis->cbInput, NULL);
    1174         AssertRC(rc);
    1175         RTFileClose(hFile);
    1176 
    1177         if (RT_FAILURE(rc))
    1178             RTFileDelete(pszFilename);
     1413        RTFILE hFile;
     1414        rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     1415        if (RT_SUCCESS(rc))
     1416        {
     1417            rc = RTFileWrite(hFile, pThis->u.Blob.pvInput, pThis->u.Blob.cbInput, NULL);
     1418            AssertRC(rc);
     1419            RTFileClose(hFile);
     1420
     1421            if (RT_FAILURE(rc))
     1422                RTFileDelete(pszFilename);
     1423        }
    11791424    }
    11801425
     
    11881433    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    11891434
    1190     return rtFuzzCtxInputAdd(pThis->pFuzzer, pThis);
     1435    return rtFuzzCtxMutationAdd(pThis->pFuzzer, pThis->pMutationTop);
    11911436}
    11921437
     
    11971442    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    11981443
     1444#if 0
    11991445    int rc = VINF_SUCCESS;
    12001446    PRTFUZZINTERMEDIATE pIntermediate = NULL;
     
    12121458    else
    12131459        rc = VERR_NOT_FOUND;
    1214 
    1215     return rc;
    1216 }
    1217 
     1460#endif
     1461
     1462    return VERR_NOT_IMPLEMENTED;
     1463}
     1464
  • trunk/src/VBox/Runtime/common/fuzz/fuzzclientcmd.cpp

    r76553 r77482  
    8585            void *pv = NULL;
    8686            size_t cb = 0;
    87             rc = RTFuzzInputQueryData(hFuzzInput, &pv, &cb);
     87            rc = RTFuzzInputQueryBlobData(hFuzzInput, &pv, &cb);
    8888            if (RT_SUCCESS(rc))
    8989            {
  • trunk/src/VBox/Runtime/common/fuzz/fuzzmastercmd.cpp

    r76553 r77482  
    637637        if (RT_LIKELY(pFuzzRun->pszId))
    638638        {
    639             rc = RTFuzzObsCreate(&pFuzzRun->hFuzzObs);
     639            rc = RTFuzzObsCreate(&pFuzzRun->hFuzzObs, RTFUZZCTXTYPE_BLOB);
    640640            if (RT_SUCCESS(rc))
    641641            {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette