VirtualBox

Changeset 77544 in vbox for trunk


Ignore:
Timestamp:
Mar 3, 2019 8:07:01 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129148
Message:

Runtime/fuzz: Updates, add a target state recording mechanism to record changes in target behavior caused by mutated inputs. This allows to decide which mutated input gets added to the input corpus and which one gets discarded. Currently this is only able to record the stdout/stderr channels of the fuzzed process but other sources to detect changed behvior will get added in the future

Location:
trunk
Files:
1 added
4 edited

Legend:

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

    r77509 r77544  
    4242
    4343/** A fuzzer context handle. */
    44 typedef struct RTFUZZCTXINT    *RTFUZZCTX;
     44typedef struct RTFUZZCTXINT      *RTFUZZCTX;
    4545/** Pointer to a fuzzer context handle. */
    46 typedef RTFUZZCTX              *PRTFUZZCTX;
     46typedef RTFUZZCTX                *PRTFUZZCTX;
    4747/** NIL fuzzer context handle. */
    48 #define NIL_RTFUZZCTX           ((RTFUZZCTX)~(uintptr_t)0)
     48#define NIL_RTFUZZCTX            ((RTFUZZCTX)~(uintptr_t)0)
    4949/** A fuzzer input handle. */
    50 typedef struct RTFUZZINPUTINT  *RTFUZZINPUT;
     50typedef struct RTFUZZINPUTINT    *RTFUZZINPUT;
    5151/** Pointer to a fuzzer input handle. */
    52 typedef RTFUZZINPUT            *PRTFUZZINPUT;
     52typedef RTFUZZINPUT              *PRTFUZZINPUT;
    5353/** NIL fuzzer input handle. */
    54 #define NIL_RTFUZZINPUT        ((RTFUZZINPUT)~(uintptr_t)0)
     54#define NIL_RTFUZZINPUT          ((RTFUZZINPUT)~(uintptr_t)0)
     55
     56
     57/** A fuzzer target recorder handler. */
     58typedef struct RTFUZZTGTRECINT   *RTFUZZTGTREC;
     59/** Pointer to a fuzzer target recorder handle. */
     60typedef RTFUZZTGTREC             *PRTFUZZTGTREC;
     61/** NIL fuzzer target recorder handle. */
     62#define NIL_RTFUZZTGTREC         ((RTFUZZTGTREC)~(uintptr_t)0)
     63/** A fuzzed target state handle. */
     64typedef struct RTFUZZTGTSTATEINT *RTFUZZTGTSTATE;
     65/** Pointer to a fuzzed target state handle. */
     66typedef RTFUZZTGTSTATE           *PRTFUZZTGTSTATE;
     67/** NIL fuzzed target state handle. */
     68#define NIL_RTFUZZTGTSTATE       ((RTFUZZTGTSTATE)~(uintptr_t)0)
    5569
    5670
    5771/** Fuzzing observer handle. */
    58 typedef struct RTFUZZOBSINT    *RTFUZZOBS;
     72typedef struct RTFUZZOBSINT      *RTFUZZOBS;
    5973/** Pointer to a fuzzing observer handle. */
    60 typedef RTFUZZOBS              *PRTFUZZOBS;
     74typedef RTFUZZOBS                *PRTFUZZOBS;
    6175/** NIL fuzzing observer handle. */
    62 #define NIL_RTFUZZOBS           ((RTFUZZOBS)~(uintptr_t)0)
     76#define NIL_RTFUZZOBS             ((RTFUZZOBS)~(uintptr_t)0)
    6377
    6478
     
    319333
    320334/**
    321  * Releases a reference from the given fuzzing input handle, destroying it when reaaching 0.
     335 * Releases a reference from the given fuzzing input handle, destroying it when reaching 0.
    322336 *
    323337 * @returns New reference count on success, 0 if the fuzzing input got destroyed.
     
    383397 */
    384398RTDECL(int) RTFuzzInputRemoveFromCtxCorpus(RTFUZZINPUT hFuzzInput);
     399
     400
     401/**
     402 * Creates a new fuzzed target recorder.
     403 *
     404 * @returns IPRT status code.
     405 * @param   phFuzzTgtRec        Where to store the handle to the fuzzed target recorder on success.
     406 */
     407RTDECL(int) RTFuzzTgtRecorderCreate(PRTFUZZTGTREC phFuzzTgtRec);
     408
     409/**
     410 * Retains a reference to the given fuzzed target recorder handle.
     411 *
     412 * @returns New reference count on success.
     413 * @param   hFuzzTgtRec         The fuzzed target recorder handle.
     414 */
     415RTDECL(uint32_t) RTFuzzTgtRecorderRetain(RTFUZZTGTREC hFuzzTgtRec);
     416
     417/**
     418 * Releases a reference from the given fuzzed target recorder handle, destroying it when reaching 0.
     419 *
     420 * @returns New reference count on success, 0 if the fuzzed target recorder got destroyed.
     421 * @param   hFuzzTgtRec         The fuzzed target recorder handle.
     422 */
     423RTDECL(uint32_t) RTFuzzTgtRecorderRelease(RTFUZZTGTREC hFuzzTgtRec);
     424
     425/**
     426 * Creates a new empty fuzzed target state.
     427 *
     428 * @returns IPRT status code.
     429 * @param   hFuzzTgtRec         The fuzzed target recorder handle.
     430 * @param   phFuzzTgtState      Where to store the handle to the fuzzed target state on success.
     431 */
     432RTDECL(int) RTFuzzTgtRecorderCreateNewState(RTFUZZTGTREC hFuzzTgtRec, PRTFUZZTGTSTATE phFuzzTgtState);
     433
     434/**
     435 * Retains a reference to the given fuzzed target state handle.
     436 *
     437 * @returns New reference count on success.
     438 * @param   hFuzzTgtState       The fuzzed target state handle.
     439 */
     440RTDECL(uint32_t) RTFuzzTgtStateRetain(RTFUZZTGTSTATE hFuzzTgtState);
     441
     442/**
     443 * Releases a reference from the given fuzzed target state handle, destroying it when reaching 0.
     444 *
     445 * @returns New reference count on success, 0 if the fuzzed target recorder got destroyed.
     446 * @param   hFuzzTgtState       The fuzzed target state handle.
     447 */
     448RTDECL(uint32_t) RTFuzzTgtStateRelease(RTFUZZTGTSTATE hFuzzTgtState);
     449
     450/**
     451 * Resets the given fuzzed target state to an empty state (keeping allocated memory).
     452 *
     453 * @returns IPRT status code.
     454 * @param   hFuzzTgtState       The fuzzed target state handle.
     455 *
     456 * @note Useful when the state is not added to the recorded set to avoid allocating memory.
     457 */
     458RTDECL(int) RTFuzzTgtStateReset(RTFUZZTGTSTATE hFuzzTgtState);
     459
     460/**
     461 * Finalizes the given fuzzed target state, making it readonly.
     462 *
     463 * @returns IPRT status code.
     464 * @param   hFuzzTgtState       The fuzzed target state handle.
     465 */
     466RTDECL(int) RTFuzzTgtStateFinalize(RTFUZZTGTSTATE hFuzzTgtState);
     467
     468/**
     469 * Adds the given state to the set for the owning target recorder.
     470 *
     471 * @returns IPRT status code.
     472 * @retval  VERR_ALREADY_EXISTS if the state is already existing in the recorder set.
     473 * @param   hFuzzTgtState       The fuzzed target state handle.
     474 *
     475 * @note This also finalizes the target state if not already done.
     476 */
     477RTDECL(int) RTFuzzTgtStateAddToRecorder(RTFUZZTGTSTATE hFuzzTgtState);
     478
     479/**
     480 * Appends the given stdout output to the given target state.
     481 *
     482 * @returns IPRT status code.
     483 * @param   hFuzzTgtState       The fuzzed target state handle.
     484 * @param   pvStdOut            Pointer to the stdout data buffer.
     485 * @param   cbStdOut            Size of the stdout data buffer in bytes.
     486 */
     487RTDECL(int) RTFuzzTgtStateAppendStdoutFromBuf(RTFUZZTGTSTATE hFuzzTgtState, const void *pvStdOut, size_t cbStdOut);
     488
     489/**
     490 * Appends the given stderr output to the given target state.
     491 *
     492 * @returns IPRT status code.
     493 * @param   hFuzzTgtState       The fuzzed target state handle.
     494 * @param   pvStdErr            Pointer to the stderr data buffer.
     495 * @param   cbStdErr            Size of the stderr data buffer in bytes.
     496 */
     497RTDECL(int) RTFuzzTgtStateAppendStderrFromBuf(RTFUZZTGTSTATE hFuzzTgtState, const void *pvStdErr, size_t cbStdErr);
     498
     499/**
     500 * Appends the given stdout output to the given target state, reading from the given pipe.
     501 *
     502 * @returns IPRT status code.
     503 * @param   hFuzzTgtState       The fuzzed target state handle.
     504 * @param   hPipe               The stdout pipe to read the data from.
     505 */
     506RTDECL(int) RTFuzzTgtStateAppendStdoutFromPipe(RTFUZZTGTSTATE hFuzzTgtState, RTPIPE hPipe);
     507
     508/**
     509 * Appends the given stderr output to the given target state, reading from the given pipe.
     510 *
     511 * @returns IPRT status code.
     512 * @param   hFuzzTgtState       The fuzzed target state handle.
     513 * @param   hPipe               The stdout pipe to read the data from.
     514 */
     515RTDECL(int) RTFuzzTgtStateAppendStderrFromPipe(RTFUZZTGTSTATE hFuzzTgtState, RTPIPE hPipe);
    385516
    386517
  • trunk/include/iprt/mangling.h

    r77509 r77544  
    10631063# define RTFuzzObsSetTestBinaryArgs                     RT_MANGLER(RTFuzzObsSetTestBinaryArgs)
    10641064# define RTFuzzObsSetTmpDirectory                       RT_MANGLER(RTFuzzObsSetTmpDirectory)
     1065# define RTFuzzTgtRecorderCreate                        RT_MANGLER(RTFuzzTgtRecorderCreate)
     1066# define RTFuzzTgtRecorderCreateNewState                RT_MANGLER(RTFuzzTgtRecorderCreateNewState)
     1067# define RTFuzzTgtRecorderRelease                       RT_MANGLER(RTFuzzTgtRecorderRelease)
     1068# define RTFuzzTgtRecorderRetain                        RT_MANGLER(RTFuzzTgtRecorderRetain)
     1069# define RTFuzzTgtStateAddToRecorder                    RT_MANGLER(RTFuzzTgtStateAddToRecorder)
     1070# define RTFuzzTgtStateAppendStderrFromBuf              RT_MANGLER(RTFuzzTgtStateAppendStderrFromBuf)
     1071# define RTFuzzTgtStateAppendStderrFromPipe             RT_MANGLER(RTFuzzTgtStateAppendStderrFromPipe)
     1072# define RTFuzzTgtStateAppendStdoutFromBuf              RT_MANGLER(RTFuzzTgtStateAppendStdoutFromBuf)
     1073# define RTFuzzTgtStateAppendStdoutFromPipe             RT_MANGLER(RTFuzzTgtStateAppendStdoutFromPipe)
     1074# define RTFuzzTgtStateFinalize                         RT_MANGLER(RTFuzzTgtStateFinalize)
     1075# define RTFuzzTgtStateRelease                          RT_MANGLER(RTFuzzTgtStateRelease)
     1076# define RTFuzzTgtStateReset                            RT_MANGLER(RTFuzzTgtStateReset)
     1077# define RTFuzzTgtStateRetain                           RT_MANGLER(RTFuzzTgtStateRetain)
    10651078# define RTGetOpt                                       RT_MANGLER(RTGetOpt)
    10661079# define RTGetOptArgvFree                               RT_MANGLER(RTGetOptArgvFree)
  • trunk/src/VBox/Runtime/common/fuzz/fuzz-observer.cpp

    r77510 r77544  
    104104    /** The fuzzing context used for this observer. */
    105105    RTFUZZCTX                   hFuzzCtx;
     106    /** The target state recorder. */
     107    RTFUZZTGTREC                hTgtRec;
    106108    /** Temp directory for input files. */
    107109    char                       *pszTmpDir;
     
    141143
    142144/**
    143  * Stdout/Stderr buffer.
    144  */
    145 typedef struct RTFUZZOBSSTDOUTERRBUF
    146 {
    147     /** Current amount buffered. */
    148     size_t                      cbBuf;
    149     /** Maxmium amount to buffer. */
    150     size_t                      cbBufMax;
    151     /** Base pointer to the data buffer. */
    152     uint8_t                     *pbBase;
    153 } RTFUZZOBSSTDOUTERRBUF;
    154 /** Pointer to a stdout/stderr buffer. */
    155 typedef RTFUZZOBSSTDOUTERRBUF *PRTFUZZOBSSTDOUTERRBUF;
    156 
    157 
    158 /**
    159145 * Worker execution context.
    160146 */
     
    185171    /** Execution time of the process. */
    186172    RTMSINTERVAL                msExec;
     173    /** The recording state handle. */
     174    RTFUZZTGTSTATE              hTgtState;
    187175    /** Current input data pointer. */
    188176    uint8_t                     *pbInputCur;
    189177    /** Number of bytes left for the input. */
    190178    size_t                      cbInputLeft;
    191     /** The stdout data buffer. */
    192     RTFUZZOBSSTDOUTERRBUF       StdOutBuf;
    193     /** The stderr data buffer. */
    194     RTFUZZOBSSTDOUTERRBUF       StdErrBuf;
    195179    /** Modified arguments vector - variable in size. */
    196180    char                        *apszArgs[1];
     
    217201typedef RTFUZZOBSVARIABLE *PRTFUZZOBSVARIABLE;
    218202
    219 
    220 /**
    221  * Initializes the given stdout/stderr buffer.
    222  *
    223  * @returns nothing.
    224  * @param   pBuf                The buffer to initialize.
    225  */
    226 static void rtFuzzObsStdOutErrBufInit(PRTFUZZOBSSTDOUTERRBUF pBuf)
    227 {
    228     pBuf->cbBuf    = 0;
    229     pBuf->cbBufMax = 0;
    230     pBuf->pbBase   = NULL;
    231 }
    232 
    233 
    234 /**
    235  * Frees all allocated resources in the given stdout/stderr buffer.
    236  *
    237  * @returns nothing.
    238  * @param   pBuf                The buffer to free.
    239  */
    240 static void rtFuzzObsStdOutErrBufFree(PRTFUZZOBSSTDOUTERRBUF pBuf)
    241 {
    242     if (pBuf->pbBase)
    243         RTMemFree(pBuf->pbBase);
    244 }
    245 
    246 
    247 /**
    248  * Clears the given stdout/stderr buffer.
    249  *
    250  * @returns nothing.
    251  * @param   pBuf                The buffer to clear.
    252  */
    253 static void rtFuzzObsStdOutErrBufClear(PRTFUZZOBSSTDOUTERRBUF pBuf)
    254 {
    255     pBuf->cbBuf = 0;
    256 }
    257 
    258 
    259 /**
    260  * Fills the given stdout/stderr buffer from the given pipe.
    261  *
    262  * @returns IPRT status code.
    263  * @param   pBuf                The buffer to fill.
    264  * @param   hPipeRead           The pipe to read from.
    265  */
    266 static int rtFuzzObsStdOutErrBufFill(PRTFUZZOBSSTDOUTERRBUF pBuf, RTPIPE hPipeRead)
    267 {
    268     int rc = VINF_SUCCESS;
    269 
    270     size_t cbRead = 0;
    271     size_t cbThisRead = 0;
    272     do
    273     {
    274         cbThisRead = pBuf->cbBufMax - pBuf->cbBuf;
    275         if (!cbThisRead)
    276         {
    277             /* Try to increase the buffer. */
    278             uint8_t *pbNew = (uint8_t *)RTMemRealloc(pBuf->pbBase, pBuf->cbBufMax + _4K);
    279             if (RT_LIKELY(pbNew))
    280             {
    281                 pBuf->cbBufMax += _4K;
    282                 pBuf->pbBase   = pbNew;
    283             }
    284             cbThisRead = pBuf->cbBufMax - pBuf->cbBuf;
    285         }
    286 
    287         if (cbThisRead)
    288         {
    289             rc = RTPipeRead(hPipeRead, pBuf->pbBase + pBuf->cbBuf, cbThisRead, &cbRead);
    290             if (RT_SUCCESS(rc))
    291                 pBuf->cbBuf += cbRead;
    292         }
    293         else
    294             rc = VERR_NO_MEMORY;
    295     } while (   RT_SUCCESS(rc)
    296              && cbRead == cbThisRead);
    297 
    298     return rc;
    299 }
    300 
    301 
    302 /**
    303  * Writes the given stdout/stderr buffer to the given filename.
    304  *
    305  * @returns IPRT status code.
    306  * @param   pBuf                The buffer to write.
    307  * @param   pszFilename         The filename to write the buffer to.
    308  */
    309 static int rtFuzzStdOutErrBufWriteToFile(PRTFUZZOBSSTDOUTERRBUF pBuf, const char *pszFilename)
    310 {
    311     RTFILE hFile;
    312     int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    313     if (RT_SUCCESS(rc))
    314     {
    315         rc = RTFileWrite(hFile, pBuf->pbBase, pBuf->cbBuf, NULL);
    316         AssertRC(rc);
    317         RTFileClose(hFile);
    318 
    319         if (RT_FAILURE(rc))
    320             RTFileDelete(pszFilename);
    321     }
    322 
    323     return rc;
    324 }
    325203
    326204
     
    456334        pExecCtx->hProc            = NIL_RTPROCESS;
    457335        pExecCtx->msExec           = 0;
    458         rtFuzzObsStdOutErrBufInit(&pExecCtx->StdOutBuf);
    459         rtFuzzObsStdOutErrBufInit(&pExecCtx->StdErrBuf);
    460 
    461         rc = RTPollSetCreate(&pExecCtx->hPollSet);
     336
     337        rc = RTFuzzTgtRecorderCreateNewState(pThis->hTgtRec, &pExecCtx->hTgtState);
    462338        if (RT_SUCCESS(rc))
    463339        {
    464             rc = RTPipeCreate(&pExecCtx->hPipeStdoutR, &pExecCtx->hPipeStdoutW, RTPIPE_C_INHERIT_WRITE);
     340            rc = RTPollSetCreate(&pExecCtx->hPollSet);
    465341            if (RT_SUCCESS(rc))
    466342            {
    467                 RTHANDLE Handle;
    468                 Handle.enmType = RTHANDLETYPE_PIPE;
    469                 Handle.u.hPipe = pExecCtx->hPipeStdoutR;
    470                 rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_READ, RTFUZZOBS_EXEC_CTX_POLL_ID_STDOUT);
    471                 AssertRC(rc);
    472 
    473                 rc = RTPipeCreate(&pExecCtx->hPipeStderrR, &pExecCtx->hPipeStderrW, RTPIPE_C_INHERIT_WRITE);
     343                rc = RTPipeCreate(&pExecCtx->hPipeStdoutR, &pExecCtx->hPipeStdoutW, RTPIPE_C_INHERIT_WRITE);
    474344                if (RT_SUCCESS(rc))
    475345                {
    476                     Handle.u.hPipe = pExecCtx->hPipeStderrR;
    477                     rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_READ, RTFUZZOBS_EXEC_CTX_POLL_ID_STDERR);
     346                    RTHANDLE Handle;
     347                    Handle.enmType = RTHANDLETYPE_PIPE;
     348                    Handle.u.hPipe = pExecCtx->hPipeStdoutR;
     349                    rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_READ, RTFUZZOBS_EXEC_CTX_POLL_ID_STDOUT);
    478350                    AssertRC(rc);
    479351
    480                     /* Create the stdin pipe handles if not a file input. */
    481                     if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN || pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT)
     352                    rc = RTPipeCreate(&pExecCtx->hPipeStderrR, &pExecCtx->hPipeStderrW, RTPIPE_C_INHERIT_WRITE);
     353                    if (RT_SUCCESS(rc))
    482354                    {
    483                         rc = RTPipeCreate(&pExecCtx->hPipeStdinR, &pExecCtx->hPipeStdinW, RTPIPE_C_INHERIT_READ);
     355                        Handle.u.hPipe = pExecCtx->hPipeStderrR;
     356                        rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_READ, RTFUZZOBS_EXEC_CTX_POLL_ID_STDERR);
     357                        AssertRC(rc);
     358
     359                        /* Create the stdin pipe handles if not a file input. */
     360                        if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN || pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT)
     361                        {
     362                            rc = RTPipeCreate(&pExecCtx->hPipeStdinR, &pExecCtx->hPipeStdinW, RTPIPE_C_INHERIT_READ);
     363                            if (RT_SUCCESS(rc))
     364                            {
     365                                pExecCtx->StdinHandle.enmType = RTHANDLETYPE_PIPE;
     366                                pExecCtx->StdinHandle.u.hPipe = pExecCtx->hPipeStdinR;
     367
     368                                Handle.u.hPipe = pExecCtx->hPipeStdinW;
     369                                rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_WRITE, RTFUZZOBS_EXEC_CTX_POLL_ID_STDIN);
     370                                AssertRC(rc);
     371                            }
     372                        }
     373                        else
     374                        {
     375                            pExecCtx->StdinHandle.enmType = RTHANDLETYPE_PIPE;
     376                            pExecCtx->StdinHandle.u.hPipe = NIL_RTPIPE;
     377                        }
     378
    484379                        if (RT_SUCCESS(rc))
    485380                        {
    486                             pExecCtx->StdinHandle.enmType = RTHANDLETYPE_PIPE;
    487                             pExecCtx->StdinHandle.u.hPipe = pExecCtx->hPipeStdinR;
    488 
    489                             Handle.u.hPipe = pExecCtx->hPipeStdinW;
    490                             rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_WRITE, RTFUZZOBS_EXEC_CTX_POLL_ID_STDIN);
    491                             AssertRC(rc);
     381                            pExecCtx->StdoutHandle.enmType = RTHANDLETYPE_PIPE;
     382                            pExecCtx->StdoutHandle.u.hPipe = pExecCtx->hPipeStdoutW;
     383                            pExecCtx->StderrHandle.enmType = RTHANDLETYPE_PIPE;
     384                            pExecCtx->StderrHandle.u.hPipe = pExecCtx->hPipeStderrW;
     385                            *ppExecCtx = pExecCtx;
     386                            return VINF_SUCCESS;
    492387                        }
     388
     389                        RTPipeClose(pExecCtx->hPipeStderrR);
     390                        RTPipeClose(pExecCtx->hPipeStderrW);
    493391                    }
    494                     else
    495                     {
    496                         pExecCtx->StdinHandle.enmType = RTHANDLETYPE_PIPE;
    497                         pExecCtx->StdinHandle.u.hPipe = NIL_RTPIPE;
    498                     }
    499 
    500                     if (RT_SUCCESS(rc))
    501                     {
    502                         pExecCtx->StdoutHandle.enmType = RTHANDLETYPE_PIPE;
    503                         pExecCtx->StdoutHandle.u.hPipe = pExecCtx->hPipeStdoutW;
    504                         pExecCtx->StderrHandle.enmType = RTHANDLETYPE_PIPE;
    505                         pExecCtx->StderrHandle.u.hPipe = pExecCtx->hPipeStderrW;
    506                         *ppExecCtx = pExecCtx;
    507                         return VINF_SUCCESS;
    508                     }
    509 
    510                     RTPipeClose(pExecCtx->hPipeStderrR);
    511                     RTPipeClose(pExecCtx->hPipeStderrW);
     392
     393                    RTPipeClose(pExecCtx->hPipeStdoutR);
     394                    RTPipeClose(pExecCtx->hPipeStdoutW);
    512395                }
    513396
    514                 RTPipeClose(pExecCtx->hPipeStdoutR);
    515                 RTPipeClose(pExecCtx->hPipeStdoutW);
    516             }
    517 
    518             RTPollSetDestroy(pExecCtx->hPollSet);
     397                RTPollSetDestroy(pExecCtx->hPollSet);
     398            }
     399
     400            RTFuzzTgtStateRelease(pExecCtx->hTgtState);
    519401        }
    520402
     
    557439    }
    558440
    559     rtFuzzObsStdOutErrBufFree(&pExecCtx->StdOutBuf);
    560     rtFuzzObsStdOutErrBufFree(&pExecCtx->StdErrBuf);
     441    if (pExecCtx->hTgtState != NIL_RTFUZZTGTSTATE)
     442        RTFuzzTgtStateRelease(pExecCtx->hTgtState);
    561443    RTMemFree(pExecCtx);
    562444}
     
    574456static int rtFuzzObsExecCtxClientRun(PRTFUZZOBSINT pThis, PRTFUZZOBSEXECCTX pExecCtx, PRTPROCSTATUS pProcStat)
    575457{
    576     rtFuzzObsStdOutErrBufClear(&pExecCtx->StdOutBuf);
    577     rtFuzzObsStdOutErrBufClear(&pExecCtx->StdErrBuf);
    578 
    579458    int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], RTENV_DEFAULT, 0 /*fFlags*/, &pExecCtx->StdinHandle,
    580459                            &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, &pExecCtx->hProc);
     
    593472                {
    594473                    Assert(fEvtsRecv & RTPOLL_EVT_READ);
    595                     rc = rtFuzzObsStdOutErrBufFill(&pExecCtx->StdOutBuf, pExecCtx->hPipeStdoutR);
     474                    rc = RTFuzzTgtStateAppendStdoutFromPipe(pExecCtx->hTgtState, pExecCtx->hPipeStdoutR);
    596475                    AssertRC(rc);
    597476                }
     
    599478                {
    600479                    Assert(fEvtsRecv & RTPOLL_EVT_READ);
    601                     rc = rtFuzzObsStdOutErrBufFill(&pExecCtx->StdErrBuf, pExecCtx->hPipeStderrR);
     480                    rc = RTFuzzTgtStateAppendStderrFromPipe(pExecCtx->hTgtState, pExecCtx->hPipeStderrR);
    602481                    AssertRC(rc);
    603482                }
     
    665544static int rtFuzzObsExecCtxClientRunFuzzingAware(PRTFUZZOBSINT pThis, PRTFUZZOBSEXECCTX pExecCtx, PRTPROCSTATUS pProcStat)
    666545{
    667     rtFuzzObsStdOutErrBufClear(&pExecCtx->StdOutBuf);
    668     rtFuzzObsStdOutErrBufClear(&pExecCtx->StdErrBuf);
    669 
    670546    int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], RTENV_DEFAULT, 0 /*fFlags*/, &pExecCtx->StdinHandle,
    671547                            &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, &pExecCtx->hProc);
     
    731607                        {
    732608                            Assert(fEvtsRecv & RTPOLL_EVT_READ);
    733                             rc = rtFuzzObsStdOutErrBufFill(&pExecCtx->StdErrBuf, pExecCtx->hPipeStderrR);
     609                            rc = RTFuzzTgtStateAppendStderrFromPipe(pExecCtx->hTgtState, pExecCtx->hPipeStderrR);
    734610                            AssertRC(rc);
    735611                        }
     
    806682            if (RT_SUCCESS(rc))
    807683            {
     684                RT_NOREF(pExecCtx);
     685#if 0
    808686                /* Stdout and Stderr. */
    809687                rc = RTPathJoin(szTmp, sizeof(szTmp), &szPath[0], "stdout");
     
    816694                    rc = rtFuzzStdOutErrBufWriteToFile(&pExecCtx->StdOutBuf, &szTmp[0]);
    817695                }
     696#endif
    818697            }
    819698        }
     
    841720        return rc;
    842721
     722    char szInput[RTPATH_MAX]; RT_ZERO(szInput);
     723    if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE)
     724    {
     725        char szFilename[32];
     726
     727        ssize_t cbBuf = RTStrPrintf2(&szFilename[0], sizeof(szFilename), "%u", pObsThrd->idObs);
     728        Assert(cbBuf > 0); RT_NOREF(cbBuf);
     729
     730        rc = RTPathJoin(szInput, sizeof(szInput), pThis->pszTmpDir, &szFilename[0]);
     731        AssertRC(rc);
     732
     733        RTFUZZOBSVARIABLE aVar[2] =
     734        {
     735            { "${INPUT}", sizeof("${INPUT}") - 1, &szInput[0] },
     736            { NULL,       0,                      NULL        }
     737        };
     738        rc = rtFuzzObsExecCtxArgvPrepare(pThis, pExecCtx, &aVar[0]);
     739        if (RT_FAILURE(rc))
     740            return rc;
     741    }
     742
    843743    while (!pObsThrd->fShutdown)
    844744    {
    845         char szInput[RTPATH_MAX];
    846 
    847745        /* Wait for work. */
    848746        if (!ASMAtomicReadU32(&pObsThrd->cInputs))
     
    868766
    869767        if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE)
    870         {
    871             char szFilename[32];
    872 
    873             ssize_t cbBuf = RTStrPrintf2(&szFilename[0], sizeof(szFilename), "%u", pObsThrd->idObs);
    874             Assert(cbBuf > 0); RT_NOREF(cbBuf);
    875 
    876             RT_ZERO(szInput);
    877             rc = RTPathJoin(szInput, sizeof(szInput), pThis->pszTmpDir, &szFilename[0]);
    878             AssertRC(rc);
    879 
    880768            rc = RTFuzzInputWriteToFile(hFuzzInput, &szInput[0]);
    881             if (RT_SUCCESS(rc))
    882             {
    883                 RTFUZZOBSVARIABLE aVar[2] = {
    884                     { "${INPUT}", sizeof("${INPUT}") - 1, &szInput[0] },
    885                     { NULL,       0,                      NULL        }
    886                 };
    887                 rc = rtFuzzObsExecCtxArgvPrepare(pThis, pExecCtx, &aVar[0]);
    888             }
    889         }
    890769        else if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN)
    891770        {
     
    923802                AssertFailed();
    924803
    925             RTFuzzInputAddToCtxCorpus(hFuzzInput);
     804            /*
     805             * Check whether we reached a known target state and add the input to the
     806             * corpus in that case.
     807             */
     808            rc = RTFuzzTgtStateAddToRecorder(pExecCtx->hTgtState);
     809            if (RT_SUCCESS(rc))
     810            {
     811                /* Add to corpus and create a new target state for the next run. */
     812                RTFuzzInputAddToCtxCorpus(hFuzzInput);
     813                RTFuzzTgtStateRelease(pExecCtx->hTgtState);
     814                pExecCtx->hTgtState = NIL_RTFUZZTGTSTATE;
     815                rc = RTFuzzTgtRecorderCreateNewState(pThis->hTgtRec, &pExecCtx->hTgtState);
     816                AssertRC(rc);
     817            }
     818            else
     819            {
     820                Assert(rc == VERR_ALREADY_EXISTS);
     821                /* Reset the state for the next run. */
     822                rc = RTFuzzTgtStateReset(pExecCtx->hTgtState);
     823                AssertRC(rc);
     824            }
    926825            RTFuzzInputRelease(hFuzzInput);
    927826
     
    11261025        if (RT_SUCCESS(rc))
    11271026        {
    1128             *phFuzzObs = pThis;
    1129             return VINF_SUCCESS;
     1027            rc = RTFuzzTgtRecorderCreate(&pThis->hTgtRec);
     1028            if (RT_SUCCESS(rc))
     1029            {
     1030                *phFuzzObs = pThis;
     1031                return VINF_SUCCESS;
     1032            }
     1033            RTFuzzCtxRelease(pThis->hFuzzCtx);
    11301034        }
    11311035
     
    11611065    if (pThis->pszBinary)
    11621066        RTStrFree(pThis->pszBinary);
     1067    RTFuzzTgtRecorderRelease(pThis->hTgtRec);
    11631068    RTFuzzCtxRelease(pThis->hFuzzCtx);
    11641069    RTMemFree(pThis);
  • trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp

    r77514 r77544  
    190190    /** Size of the mutation dependent data. */
    191191    size_t                      cbMutation;
     192    /** Flag whether the mutation is contained in the tree of the context. */
     193    bool                        fInTree;
    192194    /** Mutation dependent data, variable in size. */
    193195    uint8_t                     abMutation[1];
     
    471473
    472474/**
     475 * Destroys the given mutation.
     476 *
     477 * @returns nothing.
     478 * @param   pMutation           The mutation to destroy.
     479 */
     480static void rtFuzzMutationDestroy(PRTFUZZMUTATION pMutation)
     481{
     482    rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation);
     483}
     484
     485
     486/**
    473487 * Retains an external reference to the given mutation.
    474488 *
     
    479493{
    480494    uint32_t cRefs = ASMAtomicIncU32(&pMutation->cRefs);
    481     AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
     495    AssertMsg(   (   cRefs > 1
     496                  || pMutation->fInTree)
     497              && cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
    482498    return cRefs;
    483499}
    484500
    485501
    486 #if 0 /* unused */
    487502/**
    488503 * Releases an external reference from the given mutation.
     
    495510    uint32_t cRefs = ASMAtomicDecU32(&pMutation->cRefs);
    496511    AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
     512    if (cRefs == 0 && !pMutation->fInTree)
     513        rtFuzzMutationDestroy(pMutation);
    497514    return cRefs;
    498515}
    499 #endif
    500516
    501517
     
    519535    AssertRC(rc); RT_NOREF(rc);
    520536
     537    pMutation->fInTree = true;
    521538    return rc;
    522539}
     
    531548static PRTFUZZMUTATION rtFuzzCtxMutationPickRnd(PRTFUZZCTXINT pThis)
    532549{
    533     uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 0, ASMAtomicReadU64(&pThis->cMutations));
     550    uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 1, ASMAtomicReadU64(&pThis->cMutations));
    534551
    535552    int rc = RTSemRWRequestRead(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
     
    575592        pMutation->pMutationParent = pMutationParent;
    576593        pMutation->cbMutation      = cbAdditional;
     594        pMutation->fInTree         = false;
    577595
    578596        if (pMutationParent)
     
    583601
    584602    return pMutation;
    585 }
    586 
    587 
    588 /**
    589  * Destroys the given mutation.
    590  *
    591  * @returns nothing.
    592  * @param   pMutation           The mutation to destroy.
    593  */
    594 static void rtFuzzMutationDestroy(PRTFUZZMUTATION pMutation)
    595 {
    596     rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation);
    597603}
    598604
     
    888894        rtFuzzCtxMemoryFree(pFuzzer, pThis->u.Blob.pvInput);
    889895
     896    rtFuzzMutationRelease(pThis->pMutationTop);
    890897    rtFuzzCtxMemoryFree(pFuzzer, pThis);
    891898    RTFuzzCtxRelease(pFuzzer);
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