VirtualBox

Changeset 72940 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Jul 7, 2018 1:37:19 PM (6 years ago)
Author:
vboxsync
Message:

Runtime/RTFuzz: Some updates, add a mode where the client is aware of being fuzzed for improved efficiency. The input data is fuzzed in the client and fed to the consumer until the program crashes upon the master can reconstruct the input causing the crash because we work with deterministic random number generators. This eliminates the overhead of constantly spawning new client processes.

Location:
trunk/src/VBox/Runtime/common/fuzz
Files:
1 added
3 edited

Legend:

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

    r72650 r72940  
    111111    /** Maximum time to wait for the client to terminate until it is considered hung and killed. */
    112112    RTMSINTERVAL                msWaitMax;
    113     /** Flags controlling how the binary is executed. */
    114     uint32_t                    fFlags;
     113    /** The channel the binary expects the input. */
     114    RTFUZZOBSINPUTCHAN          enmInputChan;
    115115    /** Flag whether to shutdown the master and all workers. */
    116116    volatile bool               fShutdown;
     
    474474
    475475                    /* Create the stdin pipe handles if not a file input. */
    476                     if (!(pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE))
     476                    if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN || pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT)
    477477                    {
    478478                        rc = RTPipeCreate(&pExecCtx->hPipeStdinR, &pExecCtx->hPipeStdinW, RTPIPE_C_INHERIT_READ);
     
    537537    RTPipeClose(pExecCtx->hPipeStderrW);
    538538
    539     if (!(pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE))
     539    if (   pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN
     540        || pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT)
    540541    {
    541542        RTPipeClose(pExecCtx->hPipeStdinR);
     
    649650
    650651/**
     652 * Runs the fuzzing aware client binary pumping all data back and forth waiting for the client to crash.
     653 *
     654 * @returns IPRT status code.
     655 * @retval  VERR_TIMEOUT if the client didn't finish in the given deadline and was killed.
     656 * @param   pThis               The internal fuzzing observer state.
     657 * @param   pExecCtx            The execution context.
     658 * @param   pProcStat           Where to store the process exit status on success.
     659 */
     660static int rtFuzzObsExecCtxClientRunFuzzingAware(PRTFUZZOBSINT pThis, PRTFUZZOBSEXECCTX pExecCtx, PRTPROCSTATUS pProcStat)
     661{
     662    rtFuzzObsStdOutErrBufClear(&pExecCtx->StdOutBuf);
     663    rtFuzzObsStdOutErrBufClear(&pExecCtx->StdErrBuf);
     664
     665    int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], RTENV_DEFAULT, 0 /*fFlags*/, &pExecCtx->StdinHandle,
     666                            &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, &pExecCtx->hProc);
     667    if (RT_SUCCESS(rc))
     668    {
     669        /* Send the initial fuzzing context state over to the client. */
     670        void *pvState = NULL;
     671        size_t cbState = 0;
     672        rc = RTFuzzCtxStateExport(pThis->hFuzzCtx, &pvState, &cbState);
     673        if (RT_SUCCESS(rc))
     674        {
     675            uint32_t cbStateWr = (uint32_t)cbState;
     676            rc = RTPipeWriteBlocking(pExecCtx->hPipeStdinW, &cbStateWr, sizeof(cbStateWr), NULL);
     677            rc = RTPipeWriteBlocking(pExecCtx->hPipeStdinW, pvState, cbState, NULL);
     678            if (RT_SUCCESS(rc))
     679            {
     680                rc = RTPollSetRemove(pExecCtx->hPollSet, RTFUZZOBS_EXEC_CTX_POLL_ID_STDIN);
     681                AssertRC(rc);
     682
     683                uint64_t tsMilliesLastSignal = RTTimeSystemMilliTS();
     684                uint32_t cFuzzedInputs = 0;
     685                for (;;)
     686                {
     687                    /* Wait a bit for something to happen on one of the pipes. */
     688                    uint32_t fEvtsRecv = 0;
     689                    uint32_t idEvt = 0;
     690                    rc = RTPoll(pExecCtx->hPollSet, 10 /*cMillies*/, &fEvtsRecv, &idEvt);
     691                    if (RT_SUCCESS(rc))
     692                    {
     693                        if (idEvt == RTFUZZOBS_EXEC_CTX_POLL_ID_STDOUT)
     694                        {
     695                            Assert(fEvtsRecv & RTPOLL_EVT_READ);
     696                            for (;;)
     697                            {
     698                                char achBuf[512];
     699                                size_t cbRead = 0;
     700                                rc = RTPipeRead(pExecCtx->hPipeStdoutR, &achBuf[0], sizeof(achBuf), &cbRead);
     701                                if (RT_SUCCESS(rc))
     702                                {
     703                                    if (!cbRead)
     704                                        break;
     705
     706                                    tsMilliesLastSignal = RTTimeMilliTS();
     707                                    for (unsigned i = 0; i < cbRead; i++)
     708                                    {
     709                                        ASMAtomicIncU32(&pThis->Stats.cFuzzedInputs);
     710                                        ASMAtomicIncU32(&pThis->Stats.cFuzzedInputsPerSec);
     711
     712                                        if (achBuf[i] == '.')
     713                                            cFuzzedInputs++;
     714                                        else if (achBuf[i] == 'A')
     715                                        {
     716                                            /** @todo: Advance our fuzzer to get the added input. */
     717                                        }
     718                                    }
     719                                }
     720                                else
     721                                    break;
     722                            }
     723                            AssertRC(rc);
     724                        }
     725                        else if (idEvt == RTFUZZOBS_EXEC_CTX_POLL_ID_STDERR)
     726                        {
     727                            Assert(fEvtsRecv & RTPOLL_EVT_READ);
     728                            rc = rtFuzzObsStdOutErrBufFill(&pExecCtx->StdErrBuf, pExecCtx->hPipeStderrR);
     729                            AssertRC(rc);
     730                        }
     731                        else
     732                            AssertMsgFailed(("Invalid poll ID returned: %u!\n", idEvt));
     733                    }
     734                    else
     735                        Assert(rc == VERR_TIMEOUT);
     736
     737                    /* Check the process status. */
     738                    rc = RTProcWait(pExecCtx->hProc, RTPROCWAIT_FLAGS_NOBLOCK, pProcStat);
     739                    if (RT_SUCCESS(rc))
     740                        break;
     741                    else
     742                    {
     743                        Assert(rc == VERR_PROCESS_RUNNING);
     744                        /* Check when the last response from the client was. */
     745                        if (RTTimeSystemMilliTS() - tsMilliesLastSignal > pThis->msWaitMax)
     746                        {
     747                            rc = VERR_TIMEOUT;
     748                            break;
     749                        }
     750                    }
     751                } /* for (;;) */
     752
     753                /* Kill the process on a timeout. */
     754                if (rc == VERR_TIMEOUT)
     755                {
     756                    int rc2 = RTProcTerminate(pExecCtx->hProc);
     757                    AssertRC(rc2);
     758                }
     759            }
     760        }
     761    }
     762
     763    RTHANDLE Handle;
     764    Handle.enmType = RTHANDLETYPE_PIPE;
     765    Handle.u.hPipe = pExecCtx->hPipeStdinW;
     766    rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_WRITE, RTFUZZOBS_EXEC_CTX_POLL_ID_STDIN);
     767    AssertRC(rc);
     768
     769    return rc;
     770}
     771
     772
     773/**
    651774 * Adds the input to the results directory.
    652775 *
     
    729852        AssertPtr(pObsThrd->hFuzzInput);
    730853
    731         if (pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)
     854        if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE)
    732855        {
    733856            char szFilename[32];
     
    750873            }
    751874        }
    752         else
     875        else if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN)
    753876        {
    754877            rc = RTFuzzInputQueryData(pObsThrd->hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft);
     
    760883        {
    761884            RTPROCSTATUS ProcSts;
    762             rc = rtFuzzObsExecCtxClientRun(pThis, pExecCtx, &ProcSts);
    763             ASMAtomicIncU32(&pThis->Stats.cFuzzedInputs);
    764             ASMAtomicIncU32(&pThis->Stats.cFuzzedInputsPerSec);
     885            if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT)
     886                rc = rtFuzzObsExecCtxClientRunFuzzingAware(pThis, pExecCtx, &ProcSts);
     887            else
     888            {
     889                rc = rtFuzzObsExecCtxClientRun(pThis, pExecCtx, &ProcSts);
     890                ASMAtomicIncU32(&pThis->Stats.cFuzzedInputs);
     891                ASMAtomicIncU32(&pThis->Stats.cFuzzedInputsPerSec);
     892            }
    765893
    766894            if (RT_SUCCESS(rc))
     
    780908                AssertFailed();
    781909
    782             if (pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)
     910            if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE)
    783911                RTFileDelete(&szInput[0]);
    784912        }
     
    9481076        pThis->pszBinary     = NULL;
    9491077        pThis->papszArgs     = NULL;
    950         pThis->fFlags        = 0;
    9511078        pThis->msWaitMax     = 1000;
    9521079        pThis->hThreadGlobal = NIL_RTTHREAD;
     
    10691196
    10701197
    1071 RTDECL(int) RTFuzzObsSetTestBinary(RTFUZZOBS hFuzzObs, const char *pszBinary, uint32_t fFlags)
     1198RTDECL(int) RTFuzzObsSetTestBinary(RTFUZZOBS hFuzzObs, const char *pszBinary, RTFUZZOBSINPUTCHAN enmInputChan)
    10721199{
    10731200    PRTFUZZOBSINT pThis = hFuzzObs;
     
    10761203
    10771204    int rc = VINF_SUCCESS;
    1078     pThis->fFlags    = fFlags;
    1079     pThis->pszBinary = RTStrDup(pszBinary);
     1205    pThis->enmInputChan = enmInputChan;
     1206    pThis->pszBinary    = RTStrDup(pszBinary);
    10801207    if (RT_UNLIKELY(!pThis->pszBinary))
    10811208        rc = VERR_NO_STR_MEMORY;
     
    11461273    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    11471274    AssertReturn(cProcs <= sizeof(uint64_t) * 8, VERR_INVALID_PARAMETER);
    1148     AssertReturn(   (pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)
     1275    AssertReturn(   pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE
    11491276                 || pThis->pszTmpDir != NULL,
    11501277                 VERR_INVALID_STATE);
  • trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp

    r72571 r72940  
    3939#include <iprt/err.h>
    4040#include <iprt/file.h>
     41#include <iprt/list.h>
    4142#include <iprt/md5.h>
    4243#include <iprt/mem.h>
     
    4849
    4950
     51#define RTFUZZCTX_MAGIC UINT32_C(0xdeadc0de) /** @todo */
     52
    5053/*********************************************************************************************************************************
    5154*   Structures and Typedefs                                                                                                      *
     
    6164    /** The AVL tree core. */
    6265    AVLU64NODECORE              Core;
     66    /** Node for the global list. */
     67    RTLISTNODE                  NdInputs;
    6368    /** Reference counter. */
    6469    volatile uint32_t           cRefs;
     
    107112    /** The AVL tree for indexing the input seeds (keyed by the upper half of the MD5). */
    108113    AVLU64TREE                  TreeSeedsHigh;
     114    /** Sequential list of all inputs. */
     115    RTLISTANCHOR                LstInputs;
     116    /** Number of inputs currently in the tree. */
     117    uint32_t                    cInputs;
    109118    /** The maximum size of one input seed to generate. */
    110119    size_t                      cbInputMax;
     
    143152
    144153/**
     154 * The fuzzer state to be exported - all members are stored in little endian form.
     155 */
     156typedef struct RTFUZZCTXSTATE
     157{
     158    /** Magic value for identification. */
     159    uint32_t                    u32Magic;
     160    /** Size of the PRNG state following in bytes. */
     161    uint32_t                    cbPrng;
     162    /** Number of input descriptors following. */
     163    uint32_t                    cInputs;
     164    /** Behavioral flags. */
     165    uint32_t                    fFlagsBehavioral;
     166    /** Maximum input size to generate. */
     167    uint64_t                    cbInputMax;
     168} RTFUZZCTXSTATE;
     169/** Pointer to a fuzzing context state. */
     170typedef RTFUZZCTXSTATE *PRTFUZZCTXSTATE;
     171
     172
     173/**
    145174 * Mutator callback.
    146175 *
    147176 * @returns IPRT status code.
    148177 * @param   pThis               The fuzzer context instance.
     178 * @param   pvBuf               The input buffer to mutate.
     179 * @param   cbBuf               Size of the buffer in bytes.
    149180 * @param   ppInputMutated      Where to store the pointer to the mutated input success.
    150181 */
    151 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOR(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);
     182typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOR(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated);
    152183/** Pointer to a mutator callback. */
    153184typedef FNRTFUZZCTXMUTATOR *PFNRTFUZZCTXMUTATOR;
     
    158189*   Internal Functions                                                                                                           *
    159190*********************************************************************************************************************************/
    160 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);
    161 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);
    162 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);
    163 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);
    164 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);
    165 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);
     191static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
     192                                                 PPRTFUZZINPUTINT ppInputMutated);
     193static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
     194                                                     PPRTFUZZINPUTINT ppInputMutated);
     195static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
     196                                                            PPRTFUZZINPUTINT ppInputMutated);
     197static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
     198                                                            PPRTFUZZINPUTINT ppInputMutated);
     199static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
     200                                                    PPRTFUZZINPUTINT ppInputMutated);
     201static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf,
     202                                                            PPRTFUZZINPUTINT ppInputMutated);
    166203
    167204
     
    259296            rc = VERR_ALREADY_EXISTS;
    260297        else
     298        {
     299            RTListAppend(&pThis->LstInputs, &pInput->NdInputs);
     300            pThis->cInputs++;
    261301            RTFuzzInputRetain(pInput);
     302        }
    262303    }
    263304
     
    286327 *
    287328 * @returns Pointer to the cloned input or NULL if out of memory.
    288  * @param   pInput              The input to clone.
    289  */
    290 static PRTFUZZINPUTINT rtFuzzCtxInputClone(PRTFUZZINPUTINT pInput)
    291 {
    292     PRTFUZZINPUTINT pInpClone = (PRTFUZZINPUTINT)RTMemDup(pInput, RT_OFFSETOF(RTFUZZINPUTINT, abInput[pInput->cbInput]));
     329 * @param   pThis               The fuzzer context instance.
     330 * @param   pvBuf               The buffer to clone.
     331 * @param   cbBuf               Size of the buffer in bytes.
     332 */
     333static PRTFUZZINPUTINT rtFuzzCtxInputClone(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf)
     334{
     335    PRTFUZZINPUTINT pInpClone = (PRTFUZZINPUTINT)RTMemAllocZ(RT_OFFSETOF(RTFUZZINPUTINT, abInput[cbBuf]));
    293336    if (RT_LIKELY(pInpClone))
    294337    {
    295         pInpClone->cRefs = 1;
    296         pInpClone->Core.Key = 0;
     338        pInpClone->cRefs    = 1;
     339        pInpClone->pFuzzer  = pThis,
     340        pInpClone->cbInput  = cbBuf;
     341        memcpy(&pInpClone->abInput[0], pvBuf, cbBuf);
    297342    }
    298343
     
    349394 * Mutator callback - flips a single bit in the input.
    350395 */
    351 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)
     396static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    352397{
    353398    int rc = VINF_SUCCESS;
    354     PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis);
    355     PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pInput);
     399    PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf);
    356400    if (RT_LIKELY(pInputMutated))
    357401    {
    358         int32_t iBit = RTRandAdvS32Ex(pThis->hRand, 0, (uint32_t)pInput->cbInput * 8 - 1);
     402        int32_t iBit = RTRandAdvS32Ex(pThis->hRand, 0, (uint32_t)cbBuf * 8 - 1);
    359403        ASMBitToggle(&pInputMutated->abInput[0], iBit);
    360404        RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
     
    371415 * Mutator callback - replaces a single byte in the input.
    372416 */
    373 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)
     417static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    374418{
    375419    int rc = VINF_SUCCESS;
    376     PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis);
    377     PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pInput);
     420    PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf);
    378421    if (RT_LIKELY(pInputMutated))
    379422    {
    380         uint32_t offByte = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)pInput->cbInput - 1);
     423        uint8_t *pbBuf = (uint8_t *)pvBuf;
     424        uint32_t offByte = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1);
    381425        RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offByte], 1);
    382         if (pInput->abInput[offByte] != pInputMutated->abInput[offByte])
     426        if (pbBuf[offByte] != pInputMutated->abInput[offByte])
    383427        {
    384428            RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
     
    398442 * Mutator callback - inserts a byte sequence into the input.
    399443 */
    400 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)
     444static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    401445{
    402446    int rc = VINF_SUCCESS;
    403     PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis);
    404     if (pInput->cbInput < pThis->cbInputMax)
    405     {
    406         size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, (uint32_t)pInput->cbInput + 1, (uint32_t)pThis->cbInputMax);
    407         size_t cbInsert = cbInputMutated - pInput->cbInput;
    408         uint32_t offInsert = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)pInput->cbInput);
     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;
    409453        PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated);
    410454        if (RT_LIKELY(pInputMutated))
    411455        {
    412456            if (offInsert)
    413                 memcpy(&pInputMutated->abInput[0], &pInput->abInput[0], offInsert);
     457                memcpy(&pInputMutated->abInput[0], pbBuf, offInsert);
    414458            RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offInsert], cbInsert);
    415             memcpy(&pInputMutated->abInput[offInsert + cbInsert], &pInput->abInput[offInsert], pInput->cbInput - offInsert);
     459            memcpy(&pInputMutated->abInput[offInsert + cbInsert], &pbBuf[offInsert], cbBuf - offInsert);
    416460            RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    417461            *ppInputMutated = pInputMutated;
     
    428472 * Mutator callback - appends a byte sequence to the input.
    429473 */
    430 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)
     474static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    431475{
    432476    int rc = VINF_SUCCESS;
    433     PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis);
    434     if (pInput->cbInput < pThis->cbInputMax)
    435     {
    436         size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, (uint32_t)pInput->cbInput + 1, (uint32_t)pThis->cbInputMax);
    437         size_t cbInsert = cbInputMutated - pInput->cbInput;
     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;
    438481        PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated);
    439482        if (RT_LIKELY(pInputMutated))
    440483        {
    441             memcpy(&pInputMutated->abInput[0], &pInput->abInput[0], pInput->cbInput);
    442             RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[pInput->cbInput], cbInsert);
     484            memcpy(&pInputMutated->abInput[0], pvBuf, cbBuf);
     485            RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[cbBuf], cbInsert);
    443486            RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    444487            *ppInputMutated = pInputMutated;
     
    455498 * Mutator callback - deletes a single byte in the input.
    456499 */
    457 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)
     500static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
    458501{
    459502    int rc = VINF_SUCCESS;
    460     PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis);
    461     if (pInput->cbInput > 1)
    462     {
    463         uint32_t offDelete = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)pInput->cbInput - 1);
    464         PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, pInput->cbInput - 1);
     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);
    465508        if (RT_LIKELY(pInputMutated))
    466509        {
    467510            if (offDelete)
    468                 memcpy(&pInputMutated->abInput[0], &pInput->abInput[0], offDelete);
    469             if (offDelete < pInput->cbInput - 1)
    470                 memcpy(&pInputMutated->abInput[offDelete], &pInput->abInput[offDelete + 1], pInput->cbInput - offDelete - 1);
     511                memcpy(&pInputMutated->abInput[0], pbBuf, offDelete);
     512            if (offDelete < cbBuf - 1)
     513                memcpy(&pInputMutated->abInput[offDelete], &pbBuf[offDelete + 1], cbBuf - offDelete - 1);
    471514            RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);
    472515            *ppInputMutated = pInputMutated;
     
    483526 * Mutator callback - deletes a byte sequence in the input.
    484527 */
    485 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)
    486 {
    487     RT_NOREF(pThis, ppInputMutated);
    488     return VERR_NOT_IMPLEMENTED;
    489 }
    490 
    491 
    492 RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx)
    493 {
    494     AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
    495 
     528static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)
     529{
    496530    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
     555static PRTFUZZCTXINT rtFuzzCtxCreateEmpty(void)
     556{
    497557    PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis));
    498558    if (RT_LIKELY(pThis))
    499559    {
    500         pThis->u32Magic         = 0xdeadc0de; /** @todo */
     560        pThis->u32Magic         = RTFUZZCTX_MAGIC;
    501561        pThis->cRefs            = 1;
    502562        pThis->TreeSeedsHigh    = NULL;
    503563        pThis->cbInputMax       = UINT32_MAX;
     564        pThis->cInputs          = 0;
    504565        pThis->fFlagsBehavioral = 0;
    505         rc = RTRandAdvCreateParkMiller(&pThis->hRand);
     566        RTListInit(&pThis->LstInputs);
     567
     568        int rc = RTRandAdvCreateParkMiller(&pThis->hRand);
    506569        if (RT_SUCCESS(rc))
    507570        {
    508             RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS()); /** @todo */
    509             *phFuzzCtx = pThis;
    510             return VINF_SUCCESS;
     571            RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS());
     572            return pThis;
    511573        }
    512574
    513575        RTMemFree(pThis);
     576    }
     577
     578    return NULL;
     579}
     580
     581
     582RTDECL(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;
    514592    }
    515593    else
     
    526604    AssertReturn(cbState > 0, VERR_INVALID_PARAMETER);
    527605
    528     return VERR_NOT_IMPLEMENTED;
     606    int rc = VINF_SUCCESS;
     607    if (cbState >= sizeof(RTFUZZCTXSTATE))
     608    {
     609        RTFUZZCTXSTATE StateImport;
     610
     611        memcpy(&StateImport, pvState, sizeof(RTFUZZCTXSTATE));
     612        if (   RT_LE2H_U32(StateImport.u32Magic) == RTFUZZCTX_MAGIC
     613            && RT_LE2H_U32(StateImport.cbPrng) <= cbState - sizeof(RTFUZZCTXSTATE))
     614        {
     615            PRTFUZZCTXINT pThis = rtFuzzCtxCreateEmpty();
     616            if (RT_LIKELY(pThis))
     617            {
     618                pThis->cbInputMax       = (size_t)RT_LE2H_U64(StateImport.cbInputMax);
     619                pThis->fFlagsBehavioral = RT_LE2H_U32(StateImport.fFlagsBehavioral);
     620
     621                uint8_t *pbState = (uint8_t *)pvState;
     622                uint32_t cInputs = RT_LE2H_U32(StateImport.cInputs);
     623                rc = RTRandAdvRestoreState(pThis->hRand, (const char *)&pbState[sizeof(RTFUZZCTXSTATE)]);
     624                if (RT_SUCCESS(rc))
     625                {
     626                    /* Go through the inputs and add them. */
     627                    pbState += sizeof(RTFUZZCTXSTATE) + RT_LE2H_U32(StateImport.cbPrng);
     628                    cbState -= sizeof(RTFUZZCTXSTATE) + RT_LE2H_U32(StateImport.cbPrng);
     629
     630                    uint32_t idx = 0;
     631                    while (   idx < cInputs
     632                           && RT_SUCCESS(rc))
     633                    {
     634                        size_t cbInput = 0;
     635                        if (cbState >= sizeof(uint32_t))
     636                        {
     637                            memcpy(&cbInput, pbState, sizeof(uint32_t));
     638                            cbInput = RT_LE2H_U32(cbInput);
     639                            pbState += sizeof(uint32_t);
     640                        }
     641
     642                        if (   cbInput
     643                            && cbInput <= cbState)
     644                        {
     645                            PRTFUZZINPUTINT pInput = rtFuzzCtxInputCreate(pThis, cbInput);
     646                            if (RT_LIKELY(pInput))
     647                            {
     648                                memcpy(&pInput->abInput[0], pbState, cbInput);
     649                                RTMd5(&pInput->abInput[0], pInput->cbInput, &pInput->abMd5Hash[0]);
     650                                rc = rtFuzzCtxInputAdd(pThis, pInput);
     651                                if (RT_FAILURE(rc))
     652                                    RTMemFree(pInput);
     653                                pbState += cbInput;
     654                            }
     655                        }
     656                        else
     657                            rc = VERR_INVALID_STATE;
     658
     659                        idx++;
     660                    }
     661
     662                    if (RT_SUCCESS(rc))
     663                    {
     664                        *phFuzzCtx = pThis;
     665                        return VINF_SUCCESS;
     666                    }
     667                }
     668
     669                rtFuzzCtxDestroy(pThis);
     670            }
     671            else
     672                rc = VERR_NO_MEMORY;
     673        }
     674        else
     675            rc = VERR_INVALID_MAGIC;
     676    }
     677    else
     678        rc = VERR_INVALID_MAGIC;
     679
     680    return rc;
    529681}
    530682
     
    535687    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    536688
    537     return VERR_NOT_IMPLEMENTED;
     689    void *pv = NULL;
     690    size_t cb = 0;
     691    int rc = RTFileReadAll(pszFilename, &pv, &cb);
     692    if (RT_SUCCESS(rc))
     693    {
     694        rc = RTFuzzCtxCreateFromState(phFuzzCtx, pv, cb);
     695        RTFileReadAllFree(pv, cb);
     696    }
     697
     698    return rc;
    538699}
    539700
     
    573734    AssertPtrReturn(pcbState, VERR_INVALID_POINTER);
    574735
    575     return VERR_NOT_IMPLEMENTED;
     736    char aszPrngExport[_4K]; /* Should be plenty of room here. */
     737    size_t cbPrng = sizeof(aszPrngExport);
     738    int rc = RTRandAdvSaveState(pThis->hRand, &aszPrngExport[0], &cbPrng);
     739    if (RT_SUCCESS(rc))
     740    {
     741        RTFUZZCTXSTATE StateExport;
     742
     743        StateExport.u32Magic         = RT_H2LE_U32(RTFUZZCTX_MAGIC);
     744        StateExport.cbPrng           = RT_H2LE_U32((uint32_t)cbPrng);
     745        StateExport.cInputs          = RT_H2LE_U32(pThis->cInputs);
     746        StateExport.fFlagsBehavioral = RT_H2LE_U32(pThis->fFlagsBehavioral);
     747        StateExport.cbInputMax       = RT_H2LE_U64(pThis->cbInputMax);
     748
     749        /* Estimate the size of the required state. */
     750        size_t cbState =   sizeof(StateExport)
     751                         + cbPrng
     752                         + pThis->cInputs * ((pThis->cbInputMax < _1M ? pThis->cbInputMax : _64K) + sizeof(uint32_t)); /* For the size indicator before each input. */
     753        uint8_t *pbState = (uint8_t *)RTMemAllocZ(cbState);
     754        if (RT_LIKELY(pbState))
     755        {
     756            size_t offState = 0;
     757            memcpy(pbState, &StateExport, sizeof(StateExport));
     758            offState += sizeof(StateExport);
     759            memcpy(&pbState[offState], &aszPrngExport[0], cbPrng);
     760            offState += cbPrng;
     761
     762            /* Export each input. */
     763            PRTFUZZINPUTINT pIt;
     764            RTListForEach(&pThis->LstInputs, pIt, RTFUZZINPUTINT, NdInputs)
     765            {
     766                /* Ensure buffer size. */
     767                if (offState + pIt->cbInput + sizeof(uint32_t) > cbState)
     768                {
     769                    uint8_t *pbStateNew = (uint8_t *)RTMemRealloc(pbState, cbState + pIt->cbInput + sizeof(uint32_t));
     770                    if (RT_LIKELY(pbStateNew))
     771                    {
     772                        pbState = pbStateNew;
     773                        cbState += pIt->cbInput + sizeof(uint32_t);
     774                    }
     775                    else
     776                    {
     777                        rc = VERR_NO_MEMORY;
     778                        break;
     779                    }
     780                }
     781
     782                *(uint32_t *)&pbState[offState] = RT_H2LE_U32((uint32_t)pIt->cbInput);
     783                offState += sizeof(uint32_t);
     784                memcpy(&pbState[offState], &pIt->abInput[0], pIt->cbInput);
     785                offState += pIt->cbInput;
     786            }
     787
     788            if (RT_SUCCESS(rc))
     789            {
     790                *ppvState = pbState;
     791                *pcbState = offState;
     792            }
     793            else
     794                RTMemFree(pbState);
     795        }
     796        else
     797            rc = VERR_NO_MEMORY;
     798    }
     799
     800    return rc;
    576801}
    577802
     
    583808    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    584809
    585     return VERR_NOT_IMPLEMENTED;
     810    void *pvState = NULL;
     811    size_t cbState = 0;
     812    int rc = RTFuzzCtxStateExport(hFuzzCtx, &pvState, &cbState);
     813    if (RT_SUCCESS(rc))
     814    {
     815        RTFILE hFile;
     816
     817        rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     818        if (RT_SUCCESS(rc))
     819        {
     820            rc = RTFileWrite(hFile, pvState, cbState, NULL);
     821            RTFileClose(hFile);
     822            if (RT_FAILURE(rc))
     823                RTFileDelete(pszFilename);
     824        }
     825
     826        RTMemFree(pvState);
     827    }
     828
     829    return rc;
    586830}
    587831
     
    7971041
    7981042
     1043RTDECL(int) RTFuzzCtxReseed(RTFUZZCTX hFuzzCtx, uint64_t uSeed)
     1044{
     1045    PRTFUZZCTXINT pThis = hFuzzCtx;
     1046    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1047
     1048    RTRandAdvSeed(pThis->hRand, uSeed);
     1049    return VINF_SUCCESS;
     1050}
     1051
     1052
    7991053RTDECL(int) RTFuzzCtxInputGenerate(RTFUZZCTX hFuzzCtx, PRTFUZZINPUT phFuzzInput)
    8001054{
     
    8051059
    8061060    uint32_t cTries = 0;
     1061    PRTFUZZINPUTINT pSrc = rtFuzzCtxInputPickRnd(pThis);
    8071062    do
    8081063    {
    8091064        RTFUZZCTXMUTATOR enmMutator = (RTFUZZCTXMUTATOR)RTRandAdvU32Ex(pThis->hRand, 1, RTFUZZCTXMUTATOR_LAST);
    8101065        PRTFUZZINPUTINT pInput = NULL;
    811         rc = g_apfnMutators[enmMutator](pThis, &pInput);
     1066        rc = g_apfnMutators[enmMutator](pThis, &pSrc->abInput[0], pSrc->cbInput, &pInput);
    8121067        if (   RT_SUCCESS(rc)
    8131068            && VALID_PTR(pInput))
     
    8151070            if (pThis->fFlagsBehavioral & RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS)
    8161071                rtFuzzCtxInputAdd(pThis, pInput);
     1072            *phFuzzInput = pInput;
     1073            return rc;
     1074        }
     1075    } while (++cTries <= 50);
     1076
     1077    if (RT_SUCCESS(rc))
     1078        rc = VERR_INVALID_STATE;
     1079
     1080    return rc;
     1081}
     1082
     1083
     1084RTDECL(int) RTFuzzCtxMutateBuffer(RTFUZZCTX hFuzzCtx, void *pvBuf, size_t cbBuf, PRTFUZZINPUT phFuzzInput)
     1085{
     1086    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        {
    8171100            *phFuzzInput = pInput;
    8181101            return rc;
  • trunk/src/VBox/Runtime/common/fuzz/fuzzmastercmd.cpp

    r72649 r72940  
    6565    /** Number of processes. */
    6666    uint32_t                    cProcs;
    67     /** Maximum input size to generate. */
    68     size_t                      cbInputMax;
    6967    /** The fuzzing observer state handle. */
    7068    RTFUZZOBS                   hFuzzObs;
     69    /** Flag whether fuzzing was started. */
     70    bool                        fStarted;
    7171} RTFUZZRUN;
    7272/** Pointer to a running fuzzer state. */
     
    9191    /** Flag whether to shutdown. */
    9292    bool                        fShutdown;
    93     /** Flag whether to send a response along with the ACK. */
    94     bool                        fAckResponse;
    9593    /** The response message. */
    96     char                        aszResponse[_1K];
     94    char                        *pszResponse;
    9795} RTFUZZCMDMASTER;
    9896/** Pointer to a fuzzing master command state. */
     
    267265
    268266/**
     267 * Returns the configured input channel for the binary under test.
     268 *
     269 * @returns Selected input channel or RTFUZZOBSINPUTCHAN_INVALID if an error occurred.
     270 * @param   pszCfgItem          The config item to resolve.
     271 * @param   hJsonCfg            The JSON object containing the item.
     272 * @param   enmChanDef          Default value if the item wasn't found.
     273 * @param   pErrInfo            Where to store the error information on failure, optional.
     274 */
     275static RTFUZZOBSINPUTCHAN rtFuzzCmdMasterFuzzRunProcessCfgGetInputChan(const char *pszCfgItem, RTJSONVAL hJsonCfg, RTFUZZOBSINPUTCHAN enmChanDef, PRTERRINFO pErrInfo)
     276{
     277    RTFUZZOBSINPUTCHAN enmInputChan = RTFUZZOBSINPUTCHAN_INVALID;
     278
     279    RTJSONVAL hJsonVal;
     280    int rc = RTJsonValueQueryByName(hJsonCfg, pszCfgItem, &hJsonVal);
     281    if (rc == VERR_NOT_FOUND)
     282        enmInputChan = enmChanDef;
     283    else if (RT_SUCCESS(rc))
     284    {
     285        const char *pszBinary = RTJsonValueGetString(hJsonVal);
     286        if (pszBinary)
     287        {
     288            if (!RTStrCmp(pszBinary, "File"))
     289                enmInputChan = RTFUZZOBSINPUTCHAN_FILE;
     290            else if (!RTStrCmp(pszBinary, "Stdin"))
     291                enmInputChan = RTFUZZOBSINPUTCHAN_STDIN;
     292            else if (!RTStrCmp(pszBinary, "FuzzingAware"))
     293                enmInputChan = RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT;
     294            else
     295                rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_PARAMETER, "JSON request malformed: \"%s\" for \"%s\" is not known", pszCfgItem, pszBinary);
     296        }
     297        else
     298            rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "JSON request malformed: \"%s\" is not a string", pszCfgItem);
     299
     300        RTJsonValueRelease(hJsonVal);
     301    }
     302    else
     303        rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query \"%s\"", pszCfgItem);
     304
     305    return enmInputChan;
     306}
     307
     308
     309/**
    269310 * Processes binary related configs for the given fuzzing run.
    270311 *
     
    283324        if (RT_LIKELY(pszBinary))
    284325        {
    285             bool fFileInput = false;
    286             rc = rtFuzzCmdMasterFuzzRunProcessCfgBoolDef(&fFileInput, "FileInput", hJsonRoot, false, pErrInfo);
    287             if (RT_SUCCESS(rc))
     326            RTFUZZOBSINPUTCHAN enmInputChan = rtFuzzCmdMasterFuzzRunProcessCfgGetInputChan("InputChannel", hJsonRoot, RTFUZZOBSINPUTCHAN_STDIN, pErrInfo);
     327            if (enmInputChan != RTFUZZOBSINPUTCHAN_INVALID)
    288328            {
    289                 uint32_t fFlags = 0;
    290                 if (fFileInput)
    291                     fFlags |= RTFUZZ_OBS_BINARY_F_INPUT_FILE;
    292                 rc = RTFuzzObsSetTestBinary(pFuzzRun->hFuzzObs, pszBinary, fFlags);
     329                rc = RTFuzzObsSetTestBinary(pFuzzRun->hFuzzObs, pszBinary, enmInputChan);
    293330                if (RT_FAILURE(rc))
    294331                    rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Failed to add the binary path for the fuzzing run");
     
    635672                                    RTListAppend(&pThis->LstFuzzed, &pFuzzRun->NdFuzzed);
    636673                                    rc = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs);
    637                                     if (RT_FAILURE(rc))
     674                                    if (RT_SUCCESS(rc))
     675                                        pFuzzRun->fStarted = true;
     676                                    else
    638677                                        rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to start fuzzing with %Rrc", rc);
    639678                                }
     
    771810    if (RT_SUCCESS(rc))
    772811    {
    773         rc = RTFuzzObsExecStop(pFuzzRun->hFuzzObs);
    774         if (RT_FAILURE(rc))
    775             rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Suspending the fuzzing process failed");
     812        if (pFuzzRun->fStarted)
     813        {
     814            rc = RTFuzzObsExecStop(pFuzzRun->hFuzzObs);
     815            if (RT_SUCCESS(rc))
     816                pFuzzRun->fStarted = false;
     817            else
     818                rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Suspending the fuzzing process failed");
     819        }
    776820    }
    777821
     
    794838    if (RT_SUCCESS(rc))
    795839    {
    796         rc = rtFuzzCmdMasterFuzzRunProcessCfgU32Def(&pFuzzRun->cProcs, "FuzzingProcs", hJsonRoot, pFuzzRun->cProcs, pErrInfo);
     840        if (!pFuzzRun->fStarted)
     841        {
     842            rc = rtFuzzCmdMasterFuzzRunProcessCfgU32Def(&pFuzzRun->cProcs, "FuzzingProcs", hJsonRoot, pFuzzRun->cProcs, pErrInfo);
     843            if (RT_SUCCESS(rc))
     844            {
     845                rc = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs);
     846                if (RT_SUCCESS(rc))
     847                    pFuzzRun->fStarted = true;
     848                else
     849                    rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Resuming the fuzzing process failed");
     850            }
     851        }
     852    }
     853
     854    return rc;
     855}
     856
     857
     858/**
     859 * Processes the "SaveFuzzingState" request.
     860 *
     861 * @returns IPRT status code.
     862 * @param   pThis               The fuzzing master command state.
     863 * @param   hJsonValRoot        The root node of the JSON request.
     864 * @param   pErrInfo            Where to store the error information on failure, optional.
     865 */
     866static int rtFuzzCmdMasterProcessJsonReqSaveState(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
     867{
     868    PRTFUZZRUN pFuzzRun;
     869    int rc = rtFuzzCmdMasterQueryFuzzRunFromJson(pThis, hJsonRoot, "Id", pErrInfo, &pFuzzRun);
     870    if (RT_SUCCESS(rc))
     871    {
     872        /* Suspend fuzzing, save and resume if not stopped. */
     873        if (pFuzzRun->fStarted)
     874        {
     875            rc = RTFuzzObsExecStop(pFuzzRun->hFuzzObs);
     876            if (RT_FAILURE(rc))
     877                rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Suspending the fuzzing process failed");
     878        }
     879
    797880        if (RT_SUCCESS(rc))
    798881        {
    799             rc = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs);
    800             if (RT_FAILURE(rc))
    801                 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Resuming the fuzzing process failed");
     882            RTFUZZCTX hFuzzCtx;
     883            rc = RTFuzzObsQueryCtx(pFuzzRun->hFuzzObs, &hFuzzCtx);
     884            AssertRC(rc);
     885
     886            void *pvState = NULL;
     887            size_t cbState = 0;
     888            rc = RTFuzzCtxStateExport(hFuzzCtx, &pvState, &cbState);
     889            if (RT_SUCCESS(rc))
     890            {
     891                /* Encode to base64. */
     892                size_t cbStateStr = RTBase64EncodedLength(cbState) + 1;
     893                char *pszState = (char *)RTMemAllocZ(cbStateStr);
     894                if (pszState)
     895                {
     896                    rc = RTBase64Encode(pvState, cbState, pszState, cbStateStr, &cbStateStr);
     897                    if (RT_SUCCESS(rc))
     898                    {
     899                        /* Strip all new lines from the srting. */
     900                        size_t offStr = 0;
     901                        while (offStr < cbStateStr)
     902                        {
     903#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     904                            char *pszEol = strchr(&pszState[offStr], '\r');
     905#else
     906                            char *pszEol = strchr(&pszState[offStr], '\n');
     907#endif
     908                            if (pszEol)
     909                            {
     910                                offStr += pszEol - &pszState[offStr];
     911                                memmove(pszEol, &pszEol[RTBASE64_EOL_SIZE], cbStateStr - offStr - RTBASE64_EOL_SIZE);
     912                                cbStateStr -= RTBASE64_EOL_SIZE;
     913                            }
     914                            else
     915                                break;
     916                        }
     917
     918                        const char s_szState[] = "{ \"State\": %s }";
     919                        pThis->pszResponse = RTStrAPrintf2(s_szState, pszState);
     920                        if (RT_UNLIKELY(!pThis->pszResponse))
     921                            rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_BUFFER_OVERFLOW, "Request error: Response data buffer overflow", rc);
     922                    }
     923                    else
     924                        rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to encode the state as a base64 string");
     925                    RTMemFree(pszState);
     926                }
     927                else
     928                    rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_NO_STR_MEMORY, "Request error: Failed to allocate a state string for the response");
     929                RTMemFree(pvState);
     930            }
     931            else
     932                rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Exporting the state failed");
     933        }
     934
     935        if (pFuzzRun->fStarted)
     936        {
     937            int rc2 = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs);
     938            if (RT_FAILURE(rc2))
     939                rtFuzzCmdMasterErrorRc(pErrInfo, rc2, "Request error: Resuming the fuzzing process failed");
    802940        }
    803941    }
     
    829967                                     "  \"FuzzedInputsHang\":   %u\n"
    830968                                     "  \"FuzzedInputsCrash\":   %u\n}";
    831             ssize_t cch = RTStrPrintf2(&pThis->aszResponse[0], sizeof(pThis->aszResponse), s_szStats, Stats.cFuzzedInputsPerSec,
    832                                        Stats.cFuzzedInputs, Stats.cFuzzedInputsHang, Stats.cFuzzedInputsCrash);
    833             if (cch > 0)
    834                 pThis->fAckResponse = true;
    835             else
     969            pThis->pszResponse = RTStrAPrintf2(s_szStats, Stats.cFuzzedInputsPerSec,
     970                                               Stats.cFuzzedInputs, Stats.cFuzzedInputsHang, Stats.cFuzzedInputsCrash);
     971            if (RT_UNLIKELY(!pThis->pszResponse))
    836972                rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_BUFFER_OVERFLOW, "Request error: Response data buffer overflow", rc);
    837973        }
     
    8691005            else if (!RTStrCmp(pszReq, "ResumeFuzzing"))
    8701006                rc = rtFuzzCmdMasterProcessJsonReqResume(pThis, hJsonRoot, pErrInfo);
     1007            else if (!RTStrCmp(pszReq, "SaveFuzzingState"))
     1008                rc = rtFuzzCmdMasterProcessJsonReqSaveState(pThis, hJsonRoot, pErrInfo);
    8711009            else if (!RTStrCmp(pszReq, "QueryStats"))
    8721010                rc = rtFuzzCmdMasterProcessJsonReqQueryStats(pThis, hJsonRoot, pErrInfo);
     
    9331071{
    9341072    const char s_szSucc[] = "{ \"Status\": \"ACK\" }\n";
    935     const char s_szSuccResp[] = "{ \"Status\": \"ACK\"\n  \"Response\":\n    %s\n }\n";
     1073    const char s_szSuccResp[] = "{ \"Status\": \"ACK\"\n  \"Response\":\n";
     1074    const char s_szSuccRespClose[] = "\n }\n";
    9361075    if (pszResponse)
    9371076    {
    938         char szTmp[_1K];
    939         ssize_t cchResp = RTStrPrintf2(szTmp, sizeof(szTmp), s_szSuccResp, pszResponse);
    940         if (cchResp > 0)
    941             RTTcpWrite(hSocket, szTmp, cchResp);
    942         else
    943             RTTcpWrite(hSocket, s_szSucc, strlen(s_szSucc));
     1077        RTSGSEG aSegs[3];
     1078        RTSGBUF SgBuf;
     1079        aSegs[0].pvSeg = (void *)s_szSuccResp;
     1080        aSegs[0].cbSeg = sizeof(s_szSuccResp) - 1;
     1081        aSegs[1].pvSeg = (void *)pszResponse;
     1082        aSegs[1].cbSeg = strlen(pszResponse);
     1083        aSegs[2].pvSeg = (void *)s_szSuccRespClose;
     1084        aSegs[2].cbSeg = sizeof(s_szSuccRespClose) - 1;
     1085
     1086        RTSgBufInit(&SgBuf, &aSegs[0], RT_ELEMENTS(aSegs));
     1087        RTTcpSgWrite(hSocket, &SgBuf);
    9441088    }
    9451089    else
     
    10111155                    RTErrInfoInitStatic(&ErrInfo);
    10121156
    1013                     pThis->fAckResponse = false;
    1014                     RT_ZERO(pThis->aszResponse);
    10151157                    rc = RTJsonParseFromBuf(&hJsonReq, pbReq, cbReq, &ErrInfo.Core);
    10161158                    if (RT_SUCCESS(rc))
     
    10181160                        rc = rtFuzzCmdMasterProcessJsonReq(pThis, hJsonReq, &ErrInfo.Core);
    10191161                        if (RT_SUCCESS(rc))
    1020                             rtFuzzCmdMasterTcpSendAck(hSocket, pThis->fAckResponse ? pThis->aszResponse : NULL);
     1162                            rtFuzzCmdMasterTcpSendAck(hSocket, pThis->pszResponse);
    10211163                        else
    10221164                            rtFuzzCmdMasterTcpSendNAck(hSocket, &ErrInfo.Core);
     
    10251167                    else
    10261168                        rtFuzzCmdMasterTcpSendNAck(hSocket, &ErrInfo.Core);
     1169
     1170                    if (pThis->pszResponse)
     1171                    {
     1172                        RTStrFree(pThis->pszResponse);
     1173                        pThis->pszResponse = NULL;
     1174                    }
    10271175                    break;
    10281176                }
     
    11241272        This.pszResultsDir = NULL;
    11251273        This.fShutdown     = false;
     1274        This.pszResponse   = NULL;
    11261275
    11271276        /* Argument parsing loop. */
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