VirtualBox

Changeset 77509 in vbox


Ignore:
Timestamp:
Feb 28, 2019 7:14:03 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129108
Message:

Runtime/fuzz: Updates

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/fuzz.h

    r77482 r77509  
    7878} RTFUZZCTXTYPE;
    7979
     80
    8081/** @name RTFUZZCTX_F_XXX - Flags for RTFuzzCtxCfgSetBehavioralFlags
    8182 * @{ */
     
    8687/** @} */
    8788
     89
     90/**
     91 * Fuzzing context state export callback.
     92 *
     93 * @returns IPRT status code.
     94 * @param   hFuzzCtx            Handle of the fuzzing context.
     95 * @param   pvBuf               The data to write.
     96 * @param   cbWrite             Number of bytes to write.
     97 * @param   pvUser              Opaque user data passed in RTFuzzCtxStateExport().
     98 */
     99typedef DECLCALLBACK(int) FNRTFUZZCTXEXPORT(RTFUZZCTX hFuzzCtx, const void *pvBuf, size_t cbWrite, void *pvUser);
     100/** Pointer to a fuzzing context state export callback. */
     101typedef FNRTFUZZCTXEXPORT *PFNRTFUZZCTXEXPORT;
     102
     103/**
     104 * Fuzzing context state import callback.
     105 *
     106 * @returns IPRT status code.
     107 * @param   hFuzzCtx            Handle of the fuzzing context.
     108 * @param   pvBuf               Where to store the read data.
     109 * @param   cbRead              Number of bytes to read.
     110 * @param   pcbRead             Where to store the amount of data written, optional.
     111 * @param   pvUser              Opaque user data passed in RTFuzzCtxCreateFromState().
     112 */
     113typedef DECLCALLBACK(int) FNRTFUZZCTXIMPORT(RTFUZZCTX hFuzzCtx, void *pvBuf, size_t cbRead, size_t *pcbRead, void *pvUser);
     114/** Pointer to a fuzzing context state export callback. */
     115typedef FNRTFUZZCTXIMPORT *PFNRTFUZZCTXIMPORT;
     116
     117
    88118/**
    89119 * Creates a new fuzzing context.
     
    100130 * @returns IPRT status code.
    101131 * @param   phFuzzCtx           Where to store the handle to the fuzzing context on success.
    102  * @param   pvState             The pointer to the fuzzing state.
    103  * @param   cbState             Size of the state buffer in bytes.
    104  */
    105 RTDECL(int) RTFuzzCtxCreateFromState(PRTFUZZCTX phFuzzCtx, const void *pvState, size_t cbState);
     132 * @param   pfnImport           State import callback.
     133 * @param   pvUser              Opaque user data to pass to the callback.
     134 */
     135RTDECL(int) RTFuzzCtxCreateFromState(PRTFUZZCTX phFuzzCtx, PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
     136
     137/**
     138 * Creates a new fuzzing context loading the state from the given memory buffer.
     139 *
     140 * @returns IPRT status code.
     141 * @param   phFuzzCtx           Where to store the handle to the fuzzing context on success.
     142 * @param   pvState             Pointer to the memory containing the state.
     143 * @param   cbState             Size of the state buffer.
     144 */
     145RTDECL(int) RTFuzzCtxCreateFromStateMem(PRTFUZZCTX phFuzzCtx, const void *pvState, size_t cbState);
    106146
    107147/**
     
    135175 * @returns IPRT statuse code
    136176 * @param   hFuzzCtx            The fuzzing context to export.
    137  * @param   ppvState            Where to store the buffer of the state on success, free with RTMemFree().
    138  * @param   pcbState            Where to store the size of the context on success.
    139  */
    140 RTDECL(int) RTFuzzCtxStateExport(RTFUZZCTX hFuzzCtx, void **ppvState, size_t *pcbState);
     177 * @param   pfnExport           Export callback.
     178 * @param   pvUser              Opaque user data to pass to the callback.
     179 */
     180RTDECL(int) RTFuzzCtxStateExport(RTFUZZCTX hFuzzCtx, PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
     181
     182/**
     183 * Exports the given fuzzing context state to memory allocating the buffer.
     184 *
     185 * @returns IPRT status code.
     186 * @param   hFuzzCtx            The fuzzing context to export.
     187 * @param   ppvState            Where to store the pointer to the memory containing state on success.
     188 *                              Free with RTMemFree().
     189 * @param   pcbState            Where to store the size of the state in bytes.
     190 */
     191RTDECL(int) RTFuzzCtxStateExportToMem(RTFUZZCTX hFuzzCtx, void **ppvState, size_t *pcbState);
    141192
    142193/**
  • trunk/include/iprt/mangling.h

    r77482 r77509  
    10371037# define RTFuzzCtxCreateFromState                       RT_MANGLER(RTFuzzCtxCreateFromState)
    10381038# define RTFuzzCtxCreateFromStateFile                   RT_MANGLER(RTFuzzCtxCreateFromStateFile)
     1039# define RTFuzzCtxCreateFromStateMem                    RT_MANGLER(RTFuzzCtxCreateFromStateMem)
    10391040# define RTFuzzCtxInputGenerate                         RT_MANGLER(RTFuzzCtxInputGenerate)
    10401041# define RTFuzzCtxRelease                               RT_MANGLER(RTFuzzCtxRelease)
     
    10431044# define RTFuzzCtxStateExport                           RT_MANGLER(RTFuzzCtxStateExport)
    10441045# define RTFuzzCtxStateExportToFile                     RT_MANGLER(RTFuzzCtxStateExportToFile)
     1046# define RTFuzzCtxStateExportToMem                      RT_MANGLER(RTFuzzCtxStateExportToMem)
    10451047# define RTFuzzInputAddToCtxCorpus                      RT_MANGLER(RTFuzzInputAddToCtxCorpus)
    10461048# define RTFuzzInputMutateStreamData                    RT_MANGLER(RTFuzzInputMutateStreamData)
  • trunk/src/VBox/Runtime/common/fuzz/fuzz-observer.cpp

    r77482 r77509  
    6060#define RTFUZZOBS_EXEC_CTX_POLL_ID_STDIN  2
    6161
     62/** Length of the input queue for an observer thread. */
     63# define RTFUZZOBS_THREAD_INPUT_QUEUE_MAX       UINT32_C(5)
    6264
    6365/*********************************************************************************************************************************
     
    8183    /** Pointer to te global observer state. */
    8284    PRTFUZZOBSINT               pFuzzObs;
    83     /** Current fuzzer input. */
    84     RTFUZZINPUT                 hFuzzInput;
    85     /** Flag whether to keep the input. */
    86     bool                        fKeepInput;
    87     /** Flag whether a new input is waiting. */
    88     volatile bool               fNewInput;
     85    /** Number of inputs in the queue. */
     86    volatile uint32_t           cInputs;
     87    /** Where to insert the next input. */
     88    volatile uint32_t           offQueueInputW;
     89    /** Where to retrieve the next input from. */
     90    volatile uint32_t           offQueueInputR;
     91    /** The input queue for this thread. */
     92    RTFUZZINPUT                 ahQueueInput[RTFUZZOBS_THREAD_INPUT_QUEUE_MAX];
    8993} RTFUZZOBSTHRD;
    9094/** Pointer to an observer thread state. */
     
    670674        void *pvState = NULL;
    671675        size_t cbState = 0;
    672         rc = RTFuzzCtxStateExport(pThis->hFuzzCtx, &pvState, &cbState);
     676        rc = RTFuzzCtxStateExportToMem(pThis->hFuzzCtx, &pvState, &cbState);
    673677        if (RT_SUCCESS(rc))
    674678        {
     
    841845
    842846        /* Wait for work. */
    843         rc = RTThreadUserWait(hThrd, RT_INDEFINITE_WAIT);
    844         AssertRC(rc);
     847        if (!ASMAtomicReadU32(&pObsThrd->cInputs))
     848        {
     849            rc = RTThreadUserWait(hThrd, RT_INDEFINITE_WAIT);
     850            AssertRC(rc);
     851        }
    845852
    846853        if (pObsThrd->fShutdown)
    847854            break;
    848855
    849         if (!ASMAtomicXchgBool(&pObsThrd->fNewInput, false))
     856        if (!ASMAtomicReadU32(&pObsThrd->cInputs))
    850857            continue;
    851858
    852         AssertPtr(pObsThrd->hFuzzInput);
     859        uint32_t offRead = ASMAtomicReadU32(&pObsThrd->offQueueInputR);
     860        RTFUZZINPUT hFuzzInput = pObsThrd->ahQueueInput[offRead];
     861
     862        ASMAtomicDecU32(&pObsThrd->cInputs);
     863        offRead = (offRead + 1) % RT_ELEMENTS(pObsThrd->ahQueueInput);
     864        ASMAtomicWriteU32(&pObsThrd->offQueueInputR, offRead);
     865        if (!ASMAtomicBitTestAndSet(&pThis->bmEvt, pObsThrd->idObs))
     866            RTSemEventSignal(pThis->hEvtGlobal);
    853867
    854868        if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE)
     
    863877            AssertRC(rc);
    864878
    865             rc = RTFuzzInputWriteToFile(pObsThrd->hFuzzInput, &szInput[0]);
     879            rc = RTFuzzInputWriteToFile(hFuzzInput, &szInput[0]);
    866880            if (RT_SUCCESS(rc))
    867881            {
     
    875889        else if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN)
    876890        {
    877             rc = RTFuzzInputQueryBlobData(pObsThrd->hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft);
     891            rc = RTFuzzInputQueryBlobData(hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft);
    878892            if (RT_SUCCESS(rc))
    879893                rc = rtFuzzObsExecCtxArgvPrepare(pThis, pExecCtx, NULL);
     
    897911                {
    898912                    ASMAtomicIncU32(&pThis->Stats.cFuzzedInputsCrash);
    899                     rc = rtFuzzObsAddInputToResults(pThis, pObsThrd->hFuzzInput, pExecCtx);
     913                    rc = rtFuzzObsAddInputToResults(pThis, hFuzzInput, pExecCtx);
    900914                }
    901915            }
     
    903917            {
    904918                ASMAtomicIncU32(&pThis->Stats.cFuzzedInputsHang);
    905                 rc = rtFuzzObsAddInputToResults(pThis, pObsThrd->hFuzzInput, pExecCtx);
     919                rc = rtFuzzObsAddInputToResults(pThis, hFuzzInput, pExecCtx);
    906920            }
    907921            else
    908922                AssertFailed();
    909923
    910             ASMAtomicXchgBool(&pObsThrd->fKeepInput, true);
     924            RTFuzzInputAddToCtxCorpus(hFuzzInput);
     925            RTFuzzInputRelease(hFuzzInput);
    911926
    912927            if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE)
    913928                RTFileDelete(&szInput[0]);
    914929        }
    915 
    916         ASMAtomicBitSet(&pThis->bmEvt, pObsThrd->idObs);
    917         RTSemEventSignal(pThis->hEvtGlobal);
    918930    }
    919931
     
    924936
    925937/**
     938 * Fills the input queue of the given observer thread until it is full.
     939 *
     940 * @returns IPRT status code.
     941 * @param   pThis               Pointer to the observer instance data.
     942 * @param   pObsThrd            The observer thread instance to fill.
     943 */
     944static int rtFuzzObsMasterInputQueueFill(PRTFUZZOBSINT pThis, PRTFUZZOBSTHRD pObsThrd)
     945{
     946    int rc = VINF_SUCCESS;
     947    uint32_t cInputsAdded = 0;
     948    uint32_t cInputsAdd = RTFUZZOBS_THREAD_INPUT_QUEUE_MAX - ASMAtomicReadU32(&pObsThrd->cInputs);
     949    uint32_t offW = ASMAtomicReadU32(&pObsThrd->offQueueInputW);
     950
     951    while (   cInputsAdded < cInputsAdd
     952           && RT_SUCCESS(rc))
     953    {
     954        RTFUZZINPUT hFuzzInput = NIL_RTFUZZINPUT;
     955        rc = RTFuzzCtxInputGenerate(pThis->hFuzzCtx, &hFuzzInput);
     956        if (RT_SUCCESS(rc))
     957        {
     958            pObsThrd->ahQueueInput[offW] = hFuzzInput;
     959            offW = (offW + 1) % RTFUZZOBS_THREAD_INPUT_QUEUE_MAX;
     960            cInputsAdded++;
     961        }
     962    }
     963
     964    ASMAtomicWriteU32(&pObsThrd->offQueueInputW, offW);
     965    ASMAtomicAddU32(&pObsThrd->cInputs, cInputsAdded);
     966
     967    return rc;
     968}
     969
     970
     971/**
    926972 * Fuzzing observer master worker loop.
    927973 *
    928974 * @returns IPRT status code.
    929  * @param   hThread               The thread handle.
     975 * @param   hThread             The thread handle.
    930976 * @param   pvUser              Opaque user data.
    931977 */
     
    950996                PRTFUZZOBSTHRD pObsThrd = &pThis->paObsThreads[idxObs];
    951997
    952                 /* Release the old input. */
    953                 if (pObsThrd->hFuzzInput)
    954                 {
    955                     if (pObsThrd->fKeepInput)
    956                     {
    957                         int rc2 = RTFuzzInputAddToCtxCorpus(pObsThrd->hFuzzInput);
    958                         Assert(RT_SUCCESS(rc2) || rc2 == VERR_ALREADY_EXISTS); RT_NOREF(rc2);
    959                         pObsThrd->fKeepInput= false;
    960                     }
    961                     RTFuzzInputRelease(pObsThrd->hFuzzInput);
    962                 }
    963 
    964                 rc = RTFuzzCtxInputGenerate(pThis->hFuzzCtx, &pObsThrd->hFuzzInput);
     998                rc = rtFuzzObsMasterInputQueueFill(pThis, pObsThrd);
    965999                if (RT_SUCCESS(rc))
    966                 {
    967                     ASMAtomicWriteBool(&pObsThrd->fNewInput, true);
    9681000                    RTThreadUserSignal(pObsThrd->hThread);
    969                 }
    9701001            }
    9711002
     
    9911022static int rtFuzzObsWorkerThreadInit(PRTFUZZOBSINT pThis, uint32_t idObs, PRTFUZZOBSTHRD pObsThrd)
    9921023{
    993     pObsThrd->pFuzzObs   = pThis;
    994     pObsThrd->hFuzzInput = NULL;
    995     pObsThrd->idObs      = idObs;
    996     pObsThrd->fShutdown  = false;
     1024    pObsThrd->pFuzzObs       = pThis;
     1025    pObsThrd->idObs          = idObs;
     1026    pObsThrd->fShutdown      = false;
     1027    pObsThrd->cInputs        = 0;
     1028    pObsThrd->offQueueInputW = 0;
     1029    pObsThrd->offQueueInputR = 0;
    9971030
    9981031    ASMAtomicBitSet(&pThis->bmEvt, idObs);
     
    13181351            RTThreadUserSignal(pThrd->hThread);
    13191352            RTThreadWait(pThrd->hThread, RT_INDEFINITE_WAIT, NULL);
    1320             if (pThrd->hFuzzInput)
    1321                 RTFuzzInputRelease(pThrd->hFuzzInput);
    13221353        }
    13231354
  • trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp

    r77489 r77509  
    8787 * @param   pThis               The fuzzer context instance.
    8888 * @param   pMutation           The mutation to work on.
     89 * @param   pvMutation          Mutation dependent data.
    8990 * @param   pbBuf               The buffer to work on.
    9091 * @param   cbBuf               Size of the remaining buffer.
    9192 */
    92 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXEC(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     93typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXEC(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    9394                                                 uint8_t *pbBuf, size_t cbBuf);
    9495/** Pointer to a mutator execution callback. */
    9596typedef FNRTFUZZCTXMUTATOREXEC *PFNRTFUZZCTXMUTATOREXEC;
     97
     98
     99/**
     100 * Mutator export callback.
     101 *
     102 * @returns IPRT status code.
     103 * @param   pThis               The fuzzer context instance.
     104 * @param   pMutation           The mutation to work on.
     105 * @param   pvMutation          Mutation dependent data.
     106 * @param   pfnExport           The export callback.
     107 * @param   pvUser              Opaque user data to pass to the export callback.
     108 */
     109typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXPORT(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
     110                                                   PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
     111/** Pointer to a mutator export callback. */
     112typedef FNRTFUZZCTXMUTATOREXPORT *PFNRTFUZZCTXMUTATOREXPORT;
     113
     114
     115/**
     116 * Mutator import callback.
     117 *
     118 * @returns IPRT status code.
     119 * @param   pThis               The fuzzer context instance.
     120 * @param   pMutation           The mutation to work on.
     121 * @param   pvMutation          Mutation dependent data.
     122 * @param   pfnExport           The import callback.
     123 * @param   pvUser              Opaque user data to pass to the import callback.
     124 */
     125typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATORIMPORT(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
     126                                                   PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
     127/** Pointer to a mutator import callback. */
     128typedef FNRTFUZZCTXMUTATORIMPORT *PFNRTFUZZCTXMUTATORIMPORT;
    96129
    97130
     
    105138    /** Mutator description. */
    106139    const char                  *pszDesc;
     140    /** Mutator index. */
     141    uint32_t                    uMutator;
    107142    /** Additional flags for the mutator, controlling the behavior. */
    108143    uint64_t                    fFlags;
     
    111146    /** The execution callback. */
    112147    PFNRTFUZZCTXMUTATOREXEC     pfnExec;
     148    /** The export callback. */
     149    PFNRTFUZZCTXMUTATOREXPORT   pfnExport;
     150    /** The import callback. */
     151    PFNRTFUZZCTXMUTATORIMPORT   pfnImport;
    113152} RTFUZZMUTATOR;
    114153/** Pointer to a fuzzing mutator descriptor. */
     
    116155/** Pointer to a const fuzzing mutator descriptor. */
    117156typedef const RTFUZZMUTATOR *PCRTFUZZMUTATOR;
     157
     158/** The special corpus mutator. */
     159#define RTFUZZMUTATOR_ID_CORPUS             UINT32_C(0xffffffff)
    118160
    119161/** Mutator always works from the end of the buffer (no starting offset generation). */
     
    146188    /** Size of the generated input data in bytes after the mutation was applied. */
    147189    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;
     190    /** Size of the mutation dependent data. */
     191    size_t                      cbMutation;
     192    /** Mutation dependent data, variable in size. */
     193    uint8_t                     abMutation[1];
    160194} RTFUZZMUTATION;
    161195
     
    242276    /** Magic value for identification. */
    243277    uint32_t                    u32Magic;
     278    /** Context type. */
     279    uint32_t                    uCtxType;
    244280    /** Size of the PRNG state following in bytes. */
    245281    uint32_t                    cbPrng;
    246     /** Number of input descriptors following. */
    247     uint32_t                    cInputs;
     282    /** Number of mutator descriptors following. */
     283    uint32_t                    cMutators;
     284    /** Number of mutation descriptors following. */
     285    uint32_t                    cMutations;
    248286    /** Behavioral flags. */
    249287    uint32_t                    fFlagsBehavioral;
     
    253291/** Pointer to a fuzzing context state. */
    254292typedef RTFUZZCTXSTATE *PRTFUZZCTXSTATE;
     293
     294/** BLOB context type. */
     295#define RTFUZZCTX_STATE_TYPE_BLOB         UINT32_C(0)
     296/** Stream context type. */
     297#define RTFUZZCTX_STATE_TYPE_STREAM       UINT32_C(1)
     298
     299
     300/**
     301 * The fuzzer mutation state to be exported - all members are stored in little endian form.
     302 */
     303typedef struct RTFUZZMUTATIONSTATE
     304{
     305    /** The mutation identifier. */
     306    uint64_t                    u64Id;
     307    /** The mutation identifier of the parent, 0 for no parent. */
     308    uint64_t                    u64IdParent;
     309    /** The byte offset where the mutation starts. */
     310    uint64_t                    u64OffMutation;
     311    /** Size of input data after mutation was applied. */
     312    uint64_t                    cbInput;
     313    /** Size of mutation dependent data following. */
     314    uint64_t                    cbMutation;
     315    /** The mutator ID. */
     316    uint32_t                    u32IdMutator;
     317    /** The mutation level. */
     318    uint32_t                    iLvl;
     319    /** Magic value for identification. */
     320    uint32_t                    u32Magic;
     321} RTFUZZMUTATIONSTATE;
    255322
    256323
     
    276343
    277344
     345/**
     346 * Fuzzing context export AVL arguments.
     347 */
     348typedef struct RTFUZZEXPORTARGS
     349{
     350    /** Pointer to the export callback. */
     351    PFNRTFUZZCTXEXPORT pfnExport;
     352    /** Opaque user data to pass to the callback. */
     353    void               *pvUser;
     354} RTFUZZEXPORTARGS;
     355/** Pointer to the export arguments. */
     356typedef RTFUZZEXPORTARGS *PRTFUZZEXPORTARGS;
     357/** Pointer to the constant export arguments. */
     358typedef const RTFUZZEXPORTARGS *PCRTFUZZEXPORTARGS;
     359
    278360
    279361/*********************************************************************************************************************************
     
    291373                                                                PPRTFUZZMUTATION ppMutation);
    292374
    293 static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     375static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    294376                                                    uint8_t *pbBuf, size_t cbBuf);
    295 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     377static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    296378                                                     uint8_t *pbBuf, size_t cbBuf);
    297 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     379static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    298380                                                         uint8_t *pbBuf, size_t cbBuf);
    299 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     381static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    300382                                                                      uint8_t *pbBuf, size_t cbBuf);
    301 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     383static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    302384                                                        uint8_t *pbBuf, size_t cbBuf);
    303 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     385static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    304386                                                                uint8_t *pbBuf, size_t cbBuf);
    305387
     388static DECLCALLBACK(int) rtFuzzCtxMutatorExportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
     389                                                       PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
     390static DECLCALLBACK(int) rtFuzzCtxMutatorImportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
     391                                                      PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
    306392
    307393/*********************************************************************************************************************************
     
    317403    /** pszDesc */
    318404    "Special mutator, which is assigned to the initial corpus",
     405    /** uMutator. */
     406    RTFUZZMUTATOR_ID_CORPUS,
    319407    /** fFlags */
    320408    RTFUZZMUTATOR_F_DEFAULT,
     
    322410    NULL,
    323411    /** pfnExec */
    324     rtFuzzCtxMutatorCorpusExec
     412    rtFuzzCtxMutatorCorpusExec,
     413    /** pfnExport */
     414    rtFuzzCtxMutatorExportDefault,
     415    /** pfnImport */
     416    rtFuzzCtxMutatorImportDefault
    325417};
    326418
     
    330422static RTFUZZMUTATOR const g_aMutators[] =
    331423{
    332     /* pszId         pszDesc                                          fFlags                      pfnPrep                                       pfnExec */
    333     { "BitFlip",     "Flips a single bit in the input",               RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorBitFlipPrep,                  rtFuzzCtxMutatorBitFlipExec},
    334     { "ByteReplace", "Replaces a single byte in the input",           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteReplacePrep,              rtFuzzCtxMutatorByteReplaceExec},
    335     { "ByteSeqIns",  "Inserts a byte sequence in the input",          RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec},
    336     { "ByteSeqApp",  "Appends a byte sequence to the input",          RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec},
    337     { "ByteDelete",  "Deletes a single byte sequence from the input", RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteDeletePrep,               rtFuzzCtxMutatorByteDeleteExec},
    338     { "ByteSeqDel",  "Deletes a byte sequence from the input",        RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceDeletePrep,       rtFuzzCtxMutatorByteSequenceDeleteExec}
     424    /* pszId         pszDesc                                          uMutator     fFlags                      pfnPrep                                       pfnExec                                       pfnExport                                       pfnImport */
     425    { "BitFlip",     "Flips a single bit in the input",               0,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorBitFlipPrep,                  rtFuzzCtxMutatorBitFlipExec,                  rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
     426    { "ByteReplace", "Replaces a single byte in the input",           1,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteReplacePrep,              rtFuzzCtxMutatorByteReplaceExec,              rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
     427    { "ByteSeqIns",  "Inserts a byte sequence in the input",          2,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
     428    { "ByteSeqApp",  "Appends a byte sequence to the input",          3,           RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
     429    { "ByteDelete",  "Deletes a single byte sequence from the input", 4,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteDeletePrep,               rtFuzzCtxMutatorByteDeleteExec,               NULL,                          NULL                          },
     430    { "ByteSeqDel",  "Deletes a byte sequence from the input",        5,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceDeletePrep,       rtFuzzCtxMutatorByteSequenceDeleteExec,       NULL,                          NULL                          }
    339431};
    340432
     
    416508    int rc = VINF_SUCCESS;
    417509
    418     pMutation->Core.Key = ASMAtomicIncU64(&pThis->cMutations) - 1;
     510    pMutation->Core.Key = ASMAtomicIncU64(&pThis->cMutations);
    419511    rc = RTSemRWRequestWrite(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
    420512    AssertRC(rc); RT_NOREF(rc);
     
    465557 * @param   pMutationParent     The parent mutation, can be NULL.
    466558 * @param   cbAdditional        Additional number of bytes to allocate after the core structure.
    467  */
    468 static PRTFUZZMUTATION rtFuzzMutationCreate(PRTFUZZCTXINT pThis, uint64_t offMutation, PRTFUZZMUTATION pMutationParent, size_t cbAdditional)
     559 * @param   ppvMutation         Where to store the pointer to the mutation dependent data on success.
     560 */
     561static PRTFUZZMUTATION rtFuzzMutationCreate(PRTFUZZCTXINT pThis, uint64_t offMutation, PRTFUZZMUTATION pMutationParent,
     562                                            size_t cbAdditional, void **ppvMutation)
    469563{
    470564    PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)rtFuzzCtxMemoryAlloc(pThis, sizeof(RTFUZZMUTATION) + cbAdditional);
     
    477571        pMutation->offMutation     = offMutation;
    478572        pMutation->pMutationParent = pMutationParent;
     573        pMutation->cbMutation      = cbAdditional;
    479574
    480575        if (pMutationParent)
    481576            pMutation->iLvl = pMutationParent->iLvl + 1;
     577        if (ppvMutation)
     578            *ppvMutation = &pMutation->abMutation[0];
    482579    }
    483580
     
    510607
    511608
    512 static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     609/**
     610 * Default mutator export callback (just writing the raw data).
     611 */
     612static DECLCALLBACK(int) rtFuzzCtxMutatorExportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
     613                                                       PFNRTFUZZCTXEXPORT pfnExport, void *pvUser)
     614{
     615    return pfnExport(pThis, pvMutation, pMutation->cbMutation, pvUser);
     616}
     617
     618
     619/**
     620 * Default mutator import callback (just reading the raw data).
     621 */
     622static DECLCALLBACK(int) rtFuzzCtxMutatorImportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
     623                                                       PFNRTFUZZCTXIMPORT pfnImport, void *pvUser)
     624{
     625    return pfnImport(pThis, pvMutation, pMutation->cbMutation, NULL, pvUser);
     626}
     627
     628
     629static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    513630                                                    uint8_t *pbBuf, size_t cbBuf)
    514631{
    515     RT_NOREF(pThis, cbBuf);
    516     memcpy(pbBuf, &pMutation->u.abCorpus[0], pMutation->cbInput);
     632    RT_NOREF(pThis, cbBuf, pvMutation);
     633    memcpy(pbBuf, pvMutation, pMutation->cbInput);
    517634    return VINF_SUCCESS;
    518635}
     
    526643{
    527644    int rc = VINF_SUCCESS;
    528     PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     645    uint8_t *pidxBitFlip = 0;
     646    PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pidxBitFlip), (void **)&pidxBitFlip);
    529647    if (RT_LIKELY(pMutation))
    530648    {
    531         pMutation->cbInput      = pMutationParent->cbInput; /* Bit flips don't change the input size. */
    532         pMutation->u.idxBitFlip = RTRandAdvS32Ex(pThis->hRand, 0, sizeof(uint8_t) * 8 - 1);
     649        pMutation->cbInput = pMutationParent->cbInput; /* Bit flips don't change the input size. */
     650        *pidxBitFlip = (uint8_t)RTRandAdvU32Ex(pThis->hRand, 0, sizeof(uint8_t) * 8 - 1);
    533651        *ppMutation = pMutation;
    534652    }
     
    540658
    541659
    542 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     660static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    543661                                                     uint8_t *pbBuf, size_t cbBuf)
    544662{
    545     RT_NOREF(pThis, cbBuf);
    546     ASMBitToggle(pbBuf, pMutation->u.idxBitFlip);
     663    RT_NOREF(pThis, cbBuf, pMutation);
     664    uint8_t idxBitFlip = *(uint8_t *)pvMutation;
     665    ASMBitToggle(pbBuf, idxBitFlip);
    547666    return VINF_SUCCESS;
    548667}
     
    556675{
    557676    int rc = VINF_SUCCESS;
    558     PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     677    uint8_t *pbReplace = 0;
     678    PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pbReplace), (void **)&pbReplace);
    559679    if (RT_LIKELY(pMutation))
    560680    {
    561681        pMutation->cbInput = pMutationParent->cbInput; /* Byte replacements don't change the input size. */
    562         RTRandAdvBytes(pThis->hRand, &pMutation->u.bByteReplace, 1); /** @todo Filter out same values. */
     682        RTRandAdvBytes(pThis->hRand, pbReplace, 1); /** @todo Filter out same values. */
    563683        *ppMutation = pMutation;
    564684    }
     
    570690
    571691
    572 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     692static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    573693                                                         uint8_t *pbBuf, size_t cbBuf)
    574694{
    575     RT_NOREF(pThis, cbBuf);
    576     *pbBuf = pMutation->u.bByteReplace;
     695    RT_NOREF(pThis, cbBuf, pMutation);
     696    uint8_t bReplace = *(uint8_t *)pvMutation;
     697    *pbBuf = bReplace;
    577698    return VINF_SUCCESS;
    578699}
     
    590711        size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, pMutationParent->cbInput + 1, pThis->cbInputMax);
    591712        size_t cbInsert = cbInputMutated - pMutationParent->cbInput;
    592 
    593         PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, cbInsert);
     713        uint8_t *pbAdd = NULL;
     714
     715        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, cbInsert, (void **)&pbAdd);
    594716        if (RT_LIKELY(pMutation))
    595717        {
    596718            pMutation->cbInput = cbInputMutated;
    597             RTRandAdvBytes(pThis->hRand, &pMutation->u.abAdd[0], cbInsert);
     719            RTRandAdvBytes(pThis->hRand, pbAdd, cbInsert);
    598720            *ppMutation = pMutation;
    599721        }
     
    606728
    607729
    608 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     730static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    609731                                                                      uint8_t *pbBuf, size_t cbBuf)
    610732{
     
    616738        memmove(pbBuf + cbInsert, pbBuf, cbBuf);
    617739
    618     memcpy(pbBuf, &pMutation->u.abAdd[0], cbInsert);
     740    memcpy(pbBuf, pvMutation, cbInsert);
    619741    return VINF_SUCCESS;
    620742}
     
    630752    if (pMutationParent->cbInput - offStart >= 1)
    631753    {
    632         PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     754        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/, NULL);
    633755        if (RT_LIKELY(pMutation))
    634756        {
     
    644766
    645767
    646 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     768static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    647769                                                        uint8_t *pbBuf, size_t cbBuf)
    648770{
    649     RT_NOREF(pThis, pMutation);
     771    RT_NOREF(pThis, pMutation, pvMutation);
    650772
    651773    /* Just move the residual data to the front. */
     
    667789        size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, offStart, pMutationParent->cbInput - 1);
    668790
    669         PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/);
     791        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/, NULL);
    670792        if (RT_LIKELY(pMutation))
    671793        {
     
    681803
    682804
    683 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation,
     805static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    684806                                                                uint8_t *pbBuf, size_t cbBuf)
    685807{
    686     RT_NOREF(pThis);
     808    RT_NOREF(pThis, pvMutation);
    687809    Assert(pMutation->pMutationParent->cbInput > pMutation->cbInput);
    688810    size_t cbDel = pMutation->pMutationParent->cbInput - pMutation->cbInput;
     
    789911        {
    790912            PCRTFUZZMUTATION pMutation = pThis->apMutations[i];
    791             pMutation->pMutator->pfnExec(pThis->pFuzzer, pMutation, pbBuf + pMutation->offMutation,
     913            pMutation->pMutator->pfnExec(pThis->pFuzzer, pMutation, (void *)&pMutation->abMutation[0],
     914                                         pbBuf + pMutation->offMutation,
    792915                                         cbInputNow - pMutation->offMutation);
    793916
     
    812935
    813936
    814 RTDECL(int) RTFuzzCtxCreateFromState(PRTFUZZCTX phFuzzCtx, const void *pvState, size_t cbState)
     937RTDECL(int) RTFuzzCtxCreateFromState(PRTFUZZCTX phFuzzCtx, PFNRTFUZZCTXIMPORT pfnImport, void *pvUser)
    815938{
    816939    AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
    817     AssertPtrReturn(pvState, VERR_INVALID_POINTER);
    818     AssertReturn(cbState > 0, VERR_INVALID_PARAMETER);
     940    AssertPtrReturn(pfnImport, VERR_INVALID_POINTER);
    819941
    820942#if 0
     
    8951017    return rc;
    8961018#else
     1019    RT_NOREF(pvUser);
    8971020    return VERR_NOT_IMPLEMENTED;
    8981021#endif
     1022}
     1023
     1024
     1025RTDECL(int) RTFuzzCtxCreateFromStateMem(PRTFUZZCTX phFuzzCtx, const void *pvState, size_t cbState)
     1026{
     1027    AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
     1028    AssertPtrReturn(pvState, VERR_INVALID_POINTER);
     1029    AssertPtrReturn(cbState, VERR_INVALID_POINTER);
     1030
     1031    return VERR_NOT_IMPLEMENTED;
    8991032}
    9001033
     
    9101043    if (RT_SUCCESS(rc))
    9111044    {
    912         rc = RTFuzzCtxCreateFromState(phFuzzCtx, pv, cb);
     1045        rc = RTFuzzCtxCreateFromStateMem(phFuzzCtx, pv, cb);
    9131046        RTFileReadAllFree(pv, cb);
    9141047    }
     
    9451078
    9461079
    947 RTDECL(int) RTFuzzCtxStateExport(RTFUZZCTX hFuzzCtx, void **ppvState, size_t *pcbState)
     1080/**
     1081 * Fuzzing context export callback for a single mutation.
     1082 */
     1083static DECLCALLBACK(int) rtFuzzCtxStateExportMutations(PAVLU64NODECORE pCore, void *pvParam)
     1084{
     1085    PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)pCore;
     1086    PCRTFUZZMUTATOR pMutator = pMutation->pMutator;
     1087    PCRTFUZZEXPORTARGS pArgs = (PCRTFUZZEXPORTARGS)pvParam;
     1088    RTFUZZMUTATIONSTATE MutationState;
     1089
     1090    MutationState.u64Id           = RT_H2LE_U64(pMutation->Core.Key);
     1091    if (pMutation->pMutationParent)
     1092        MutationState.u64IdParent = RT_H2LE_U64(pMutation->pMutationParent->Core.Key);
     1093    else
     1094        MutationState.u64IdParent = RT_H2LE_U64(0);
     1095    MutationState.u64OffMutation  = RT_H2LE_U64(pMutation->offMutation);
     1096    MutationState.cbInput         = RT_H2LE_U64((uint64_t)pMutation->cbInput);
     1097    MutationState.cbMutation      = RT_H2LE_U64((uint64_t)pMutation->cbMutation);
     1098    MutationState.u32IdMutator    = RT_H2LE_U32(pMutator->uMutator);
     1099    MutationState.iLvl            = RT_H2LE_U32(pMutation->iLvl);
     1100    MutationState.u32Magic        = RT_H2LE_U32(pMutation->u32Magic);
     1101
     1102    int rc = pArgs->pfnExport(pMutation->pFuzzer, &MutationState, sizeof(MutationState), pArgs->pvUser);
     1103    if (   RT_SUCCESS(rc)
     1104        && pMutator->pfnExport)
     1105        rc = pMutator->pfnExport(pMutation->pFuzzer, pMutation, &pMutation->abMutation[0], pArgs->pfnExport, pArgs->pvUser);
     1106    return rc;
     1107}
     1108
     1109
     1110RTDECL(int) RTFuzzCtxStateExport(RTFUZZCTX hFuzzCtx, PFNRTFUZZCTXEXPORT pfnExport, void *pvUser)
     1111{
     1112    PRTFUZZCTXINT pThis = hFuzzCtx;
     1113    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1114    AssertPtrReturn(pfnExport, VERR_INVALID_POINTER);
     1115
     1116    char aszPrngExport[_4K]; /* Should be plenty of room here. */
     1117    size_t cbPrng = sizeof(aszPrngExport);
     1118    int rc = RTRandAdvSaveState(pThis->hRand, &aszPrngExport[0], &cbPrng);
     1119    if (RT_SUCCESS(rc))
     1120    {
     1121        RTFUZZCTXSTATE StateExport;
     1122
     1123        StateExport.u32Magic         = RT_H2LE_U32(RTFUZZCTX_MAGIC);
     1124        switch (pThis->enmType)
     1125        {
     1126            case RTFUZZCTXTYPE_BLOB:
     1127                StateExport.uCtxType = RT_H2LE_U32(RTFUZZCTX_STATE_TYPE_BLOB);
     1128                break;
     1129            case RTFUZZCTXTYPE_STREAM:
     1130                StateExport.uCtxType = RT_H2LE_U32(RTFUZZCTX_STATE_TYPE_STREAM);
     1131                break;
     1132            default:
     1133                AssertFailed();
     1134                break;
     1135        }
     1136        StateExport.cbPrng           = RT_H2LE_U32((uint32_t)cbPrng);
     1137        StateExport.cMutations       = RT_H2LE_U32(pThis->cMutations);
     1138        StateExport.cMutators        = RT_H2LE_U32(pThis->cMutators);
     1139        StateExport.fFlagsBehavioral = RT_H2LE_U32(pThis->fFlagsBehavioral);
     1140        StateExport.cbInputMax       = RT_H2LE_U64(pThis->cbInputMax);
     1141
     1142        /* Write the context state and PRNG state first. */
     1143        rc = pfnExport(pThis, &StateExport, sizeof(StateExport), pvUser);
     1144        if (RT_SUCCESS(rc))
     1145            rc = pfnExport(pThis, &aszPrngExport[0], cbPrng, pvUser);
     1146        if (RT_SUCCESS(rc))
     1147        {
     1148            /* Write the mutator descriptors next. */
     1149            for (uint32_t i = 0; i < pThis->cMutators && RT_SUCCESS(rc); i++)
     1150            {
     1151                PRTFUZZMUTATOR pMutator = &pThis->paMutators[i];
     1152                uint32_t cchId = (uint32_t)strlen(pMutator->pszId) + 1;
     1153                uint32_t cchIdW = RT_H2LE_U32(cchId);
     1154
     1155                rc = pfnExport(pThis, &cchIdW, sizeof(cchIdW), pvUser);
     1156                if (RT_SUCCESS(rc))
     1157                    rc = pfnExport(pThis, &pMutator->pszId[0], cchId, pvUser);
     1158            }
     1159        }
     1160
     1161        /* Write the mutations last. */
     1162        if (RT_SUCCESS(rc))
     1163        {
     1164            RTFUZZEXPORTARGS Args;
     1165
     1166            Args.pfnExport = pfnExport;
     1167            Args.pvUser    = pvUser;
     1168            rc = RTAvlU64DoWithAll(&pThis->TreeMutations, true /*fFromLeft*/, rtFuzzCtxStateExportMutations, &Args);
     1169        }
     1170    }
     1171
     1172    return rc;
     1173}
     1174
     1175
     1176RTDECL(int) RTFuzzCtxStateExportToMem(RTFUZZCTX hFuzzCtx, void **ppvState, size_t *pcbState)
    9481177{
    9491178    PRTFUZZCTXINT pThis = hFuzzCtx;
     
    9521181    AssertPtrReturn(pcbState, VERR_INVALID_POINTER);
    9531182
    954 #if 0
    955     char aszPrngExport[_4K]; /* Should be plenty of room here. */
    956     size_t cbPrng = sizeof(aszPrngExport);
    957     int rc = RTRandAdvSaveState(pThis->hRand, &aszPrngExport[0], &cbPrng);
    958     if (RT_SUCCESS(rc))
    959     {
    960         RTFUZZCTXSTATE StateExport;
    961 
    962         StateExport.u32Magic         = RT_H2LE_U32(RTFUZZCTX_MAGIC);
    963         StateExport.cbPrng           = RT_H2LE_U32((uint32_t)cbPrng);
    964         StateExport.cInputs          = RT_H2LE_U32(pThis->cInputs);
    965         StateExport.fFlagsBehavioral = RT_H2LE_U32(pThis->fFlagsBehavioral);
    966         StateExport.cbInputMax       = RT_H2LE_U64(pThis->cbInputMax);
    967 
    968         /* Estimate the size of the required state. */
    969         size_t cbState =   sizeof(StateExport)
    970                          + cbPrng
    971                          + pThis->cInputs * ((pThis->cbInputMax < _1M ? pThis->cbInputMax : _64K) + sizeof(uint32_t)); /* For the size indicator before each input. */
    972         uint8_t *pbState = (uint8_t *)RTMemAllocZ(cbState);
    973         if (RT_LIKELY(pbState))
    974         {
    975             size_t offState = 0;
    976             memcpy(pbState, &StateExport, sizeof(StateExport));
    977             offState += sizeof(StateExport);
    978             memcpy(&pbState[offState], &aszPrngExport[0], cbPrng);
    979             offState += cbPrng;
    980 
    981             /* Export each input. */
    982             PRTFUZZINPUTINT pIt;
    983             RTListForEach(&pThis->LstInputs, pIt, RTFUZZINPUTINT, NdInputs)
    984             {
    985                 /* Ensure buffer size. */
    986                 if (offState + pIt->cbInput + sizeof(uint32_t) > cbState)
    987                 {
    988                     uint8_t *pbStateNew = (uint8_t *)RTMemRealloc(pbState, cbState + pIt->cbInput + sizeof(uint32_t));
    989                     if (RT_LIKELY(pbStateNew))
    990                     {
    991                         pbState = pbStateNew;
    992                         cbState += pIt->cbInput + sizeof(uint32_t);
    993                     }
    994                     else
    995                     {
    996                         rc = VERR_NO_MEMORY;
    997                         break;
    998                     }
    999                 }
    1000 
    1001                 *(uint32_t *)&pbState[offState] = RT_H2LE_U32((uint32_t)pIt->cbInput);
    1002                 offState += sizeof(uint32_t);
    1003                 memcpy(&pbState[offState], &pIt->abInput[0], pIt->cbInput);
    1004                 offState += pIt->cbInput;
    1005             }
    1006 
    1007             if (RT_SUCCESS(rc))
    1008             {
    1009                 *ppvState = pbState;
    1010                 *pcbState = offState;
    1011             }
    1012             else
    1013                 RTMemFree(pbState);
    1014         }
    1015         else
    1016             rc = VERR_NO_MEMORY;
    1017     }
    1018 
    1019     return rc;
    1020 #else
    10211183    return VERR_NOT_IMPLEMENTED;
    1022 #endif
     1184}
     1185
     1186
     1187/**
     1188 * Export to file callback.
     1189 */
     1190DECLCALLBACK(int) rtFuzzCtxStateExportFile(RTFUZZCTX hFuzzCtx, const void *pvBuf, size_t cbWrite, void *pvUser)
     1191{
     1192    RT_NOREF(hFuzzCtx);
     1193
     1194    RTFILE hFile = (RTFILE)pvUser;
     1195    return RTFileWrite(hFile, pvBuf, cbWrite, NULL);
    10231196}
    10241197
     
    10301203    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    10311204
    1032     void *pvState = NULL;
    1033     size_t cbState = 0;
    1034     int rc = RTFuzzCtxStateExport(hFuzzCtx, &pvState, &cbState);
     1205    RTFILE hFile;
     1206    int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    10351207    if (RT_SUCCESS(rc))
    10361208    {
    1037         RTFILE hFile;
    1038 
    1039         rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    1040         if (RT_SUCCESS(rc))
    1041         {
    1042             rc = RTFileWrite(hFile, pvState, cbState, NULL);
    1043             RTFileClose(hFile);
    1044             if (RT_FAILURE(rc))
    1045                 RTFileDelete(pszFilename);
    1046         }
    1047 
    1048         RTMemFree(pvState);
     1209        rc = RTFuzzCtxStateExport(hFuzzCtx, rtFuzzCtxStateExportFile, hFile);
     1210        RTFileClose(hFile);
     1211        if (RT_FAILURE(rc))
     1212            RTFileDelete(pszFilename);
    10491213    }
    10501214
     
    10611225
    10621226    int rc = VINF_SUCCESS;
    1063     PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbInput);
     1227    void *pvCorpus = NULL;
     1228    PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbInput, &pvCorpus);
    10641229    if (RT_LIKELY(pMutation))
    10651230    {
    10661231        pMutation->pMutator = &g_MutatorCorpus;
    10671232        pMutation->cbInput  = cbInput;
    1068         memcpy(&pMutation->u.abCorpus[0], pvInput, cbInput);
     1233        memcpy(pvCorpus, pvInput, cbInput);
    10691234        rc = rtFuzzCtxMutationAdd(pThis, pMutation);
    10701235        if (RT_FAILURE(rc))
     
    11041269
    11051270    uint64_t cbFile = 0;
     1271    void *pvCorpus = NULL;
    11061272    int rc = RTVfsFileGetSize(hVfsFile, &cbFile);
    11071273    if (RT_SUCCESS(rc))
    11081274    {
    1109         PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbFile);
     1275        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbFile, &pvCorpus);
    11101276        if (RT_LIKELY(pMutation))
    11111277        {
    11121278            pMutation->pMutator = &g_MutatorCorpus;
    11131279            pMutation->cbInput  = cbFile;
    1114             rc = RTVfsFileRead(hVfsFile, &pMutation->u.abCorpus[0], cbFile, NULL);
     1280            rc = RTVfsFileRead(hVfsFile, pvCorpus, cbFile, NULL);
    11151281            if (RT_SUCCESS(rc))
    11161282                rc = rtFuzzCtxMutationAdd(pThis, pMutation);
  • trunk/src/VBox/Runtime/common/fuzz/fuzzclientcmd.cpp

    r77482 r77509  
    133133                    if (RT_SUCCESS(rc))
    134134                    {
    135                         rc = RTFuzzCtxCreateFromState(&pThis->hFuzzCtx, pvFuzzCtxState, cbFuzzCtxState);
     135                        rc = RTFuzzCtxCreateFromStateMem(&pThis->hFuzzCtx, pvFuzzCtxState, cbFuzzCtxState);
    136136                        if (RT_SUCCESS(rc))
    137137                            rc = rtFuzzCmdClientMainloop(pThis);
  • trunk/src/VBox/Runtime/common/fuzz/fuzzmastercmd.cpp

    r77482 r77509  
    886886            void *pvState = NULL;
    887887            size_t cbState = 0;
    888             rc = RTFuzzCtxStateExport(hFuzzCtx, &pvState, &cbState);
     888            rc = RTFuzzCtxStateExportToMem(hFuzzCtx, &pvState, &cbState);
    889889            if (RT_SUCCESS(rc))
    890890            {
Note: See TracChangeset for help on using the changeset viewer.

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