Changeset 72940 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Jul 7, 2018 1:37:19 PM (6 years ago)
- 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 111 111 /** Maximum time to wait for the client to terminate until it is considered hung and killed. */ 112 112 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; 115 115 /** Flag whether to shutdown the master and all workers. */ 116 116 volatile bool fShutdown; … … 474 474 475 475 /* 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) 477 477 { 478 478 rc = RTPipeCreate(&pExecCtx->hPipeStdinR, &pExecCtx->hPipeStdinW, RTPIPE_C_INHERIT_READ); … … 537 537 RTPipeClose(pExecCtx->hPipeStderrW); 538 538 539 if (!(pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)) 539 if ( pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN 540 || pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT) 540 541 { 541 542 RTPipeClose(pExecCtx->hPipeStdinR); … … 649 650 650 651 /** 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 */ 660 static 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 /** 651 774 * Adds the input to the results directory. 652 775 * … … 729 852 AssertPtr(pObsThrd->hFuzzInput); 730 853 731 if (pThis-> fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)854 if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE) 732 855 { 733 856 char szFilename[32]; … … 750 873 } 751 874 } 752 else 875 else if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN) 753 876 { 754 877 rc = RTFuzzInputQueryData(pObsThrd->hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft); … … 760 883 { 761 884 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 } 765 893 766 894 if (RT_SUCCESS(rc)) … … 780 908 AssertFailed(); 781 909 782 if (pThis-> fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)910 if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE) 783 911 RTFileDelete(&szInput[0]); 784 912 } … … 948 1076 pThis->pszBinary = NULL; 949 1077 pThis->papszArgs = NULL; 950 pThis->fFlags = 0;951 1078 pThis->msWaitMax = 1000; 952 1079 pThis->hThreadGlobal = NIL_RTTHREAD; … … 1069 1196 1070 1197 1071 RTDECL(int) RTFuzzObsSetTestBinary(RTFUZZOBS hFuzzObs, const char *pszBinary, uint32_t fFlags)1198 RTDECL(int) RTFuzzObsSetTestBinary(RTFUZZOBS hFuzzObs, const char *pszBinary, RTFUZZOBSINPUTCHAN enmInputChan) 1072 1199 { 1073 1200 PRTFUZZOBSINT pThis = hFuzzObs; … … 1076 1203 1077 1204 int rc = VINF_SUCCESS; 1078 pThis-> fFlags = fFlags;1079 pThis->pszBinary = RTStrDup(pszBinary);1205 pThis->enmInputChan = enmInputChan; 1206 pThis->pszBinary = RTStrDup(pszBinary); 1080 1207 if (RT_UNLIKELY(!pThis->pszBinary)) 1081 1208 rc = VERR_NO_STR_MEMORY; … … 1146 1273 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1147 1274 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 1149 1276 || pThis->pszTmpDir != NULL, 1150 1277 VERR_INVALID_STATE); -
trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp
r72571 r72940 39 39 #include <iprt/err.h> 40 40 #include <iprt/file.h> 41 #include <iprt/list.h> 41 42 #include <iprt/md5.h> 42 43 #include <iprt/mem.h> … … 48 49 49 50 51 #define RTFUZZCTX_MAGIC UINT32_C(0xdeadc0de) /** @todo */ 52 50 53 /********************************************************************************************************************************* 51 54 * Structures and Typedefs * … … 61 64 /** The AVL tree core. */ 62 65 AVLU64NODECORE Core; 66 /** Node for the global list. */ 67 RTLISTNODE NdInputs; 63 68 /** Reference counter. */ 64 69 volatile uint32_t cRefs; … … 107 112 /** The AVL tree for indexing the input seeds (keyed by the upper half of the MD5). */ 108 113 AVLU64TREE TreeSeedsHigh; 114 /** Sequential list of all inputs. */ 115 RTLISTANCHOR LstInputs; 116 /** Number of inputs currently in the tree. */ 117 uint32_t cInputs; 109 118 /** The maximum size of one input seed to generate. */ 110 119 size_t cbInputMax; … … 143 152 144 153 /** 154 * The fuzzer state to be exported - all members are stored in little endian form. 155 */ 156 typedef 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. */ 170 typedef RTFUZZCTXSTATE *PRTFUZZCTXSTATE; 171 172 173 /** 145 174 * Mutator callback. 146 175 * 147 176 * @returns IPRT status code. 148 177 * @param pThis The fuzzer context instance. 178 * @param pvBuf The input buffer to mutate. 179 * @param cbBuf Size of the buffer in bytes. 149 180 * @param ppInputMutated Where to store the pointer to the mutated input success. 150 181 */ 151 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOR(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated);182 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOR(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated); 152 183 /** Pointer to a mutator callback. */ 153 184 typedef FNRTFUZZCTXMUTATOR *PFNRTFUZZCTXMUTATOR; … … 158 189 * Internal Functions * 159 190 *********************************************************************************************************************************/ 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); 191 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 192 PPRTFUZZINPUTINT ppInputMutated); 193 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 194 PPRTFUZZINPUTINT ppInputMutated); 195 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 196 PPRTFUZZINPUTINT ppInputMutated); 197 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 198 PPRTFUZZINPUTINT ppInputMutated); 199 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 200 PPRTFUZZINPUTINT ppInputMutated); 201 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 202 PPRTFUZZINPUTINT ppInputMutated); 166 203 167 204 … … 259 296 rc = VERR_ALREADY_EXISTS; 260 297 else 298 { 299 RTListAppend(&pThis->LstInputs, &pInput->NdInputs); 300 pThis->cInputs++; 261 301 RTFuzzInputRetain(pInput); 302 } 262 303 } 263 304 … … 286 327 * 287 328 * @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 */ 333 static PRTFUZZINPUTINT rtFuzzCtxInputClone(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf) 334 { 335 PRTFUZZINPUTINT pInpClone = (PRTFUZZINPUTINT)RTMemAllocZ(RT_OFFSETOF(RTFUZZINPUTINT, abInput[cbBuf])); 293 336 if (RT_LIKELY(pInpClone)) 294 337 { 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); 297 342 } 298 343 … … 349 394 * Mutator callback - flips a single bit in the input. 350 395 */ 351 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)396 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 352 397 { 353 398 int rc = VINF_SUCCESS; 354 PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis); 355 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pInput); 399 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf); 356 400 if (RT_LIKELY(pInputMutated)) 357 401 { 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); 359 403 ASMBitToggle(&pInputMutated->abInput[0], iBit); 360 404 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); … … 371 415 * Mutator callback - replaces a single byte in the input. 372 416 */ 373 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)417 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 374 418 { 375 419 int rc = VINF_SUCCESS; 376 PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis); 377 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pInput); 420 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf); 378 421 if (RT_LIKELY(pInputMutated)) 379 422 { 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); 381 425 RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offByte], 1); 382 if (p Input->abInput[offByte] != pInputMutated->abInput[offByte])426 if (pbBuf[offByte] != pInputMutated->abInput[offByte]) 383 427 { 384 428 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); … … 398 442 * Mutator callback - inserts a byte sequence into the input. 399 443 */ 400 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)444 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 401 445 { 402 446 int rc = VINF_SUCCESS; 403 PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis);404 if (pInput->cbInput < pThis->cbInputMax)405 {406 size_t cbIn putMutated = RTRandAdvU32Ex(pThis->hRand, (uint32_t)pInput->cbInput + 1, (uint32_t)pThis->cbInputMax);407 size_t cbInsert = cbInputMutated - pInput->cbInput;408 uint 32_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; 409 453 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated); 410 454 if (RT_LIKELY(pInputMutated)) 411 455 { 412 456 if (offInsert) 413 memcpy(&pInputMutated->abInput[0], &pInput->abInput[0], offInsert);457 memcpy(&pInputMutated->abInput[0], pbBuf, offInsert); 414 458 RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offInsert], cbInsert); 415 memcpy(&pInputMutated->abInput[offInsert + cbInsert], &p Input->abInput[offInsert], pInput->cbInput- offInsert);459 memcpy(&pInputMutated->abInput[offInsert + cbInsert], &pbBuf[offInsert], cbBuf - offInsert); 416 460 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 417 461 *ppInputMutated = pInputMutated; … … 428 472 * Mutator callback - appends a byte sequence to the input. 429 473 */ 430 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)474 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 431 475 { 432 476 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; 438 481 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated); 439 482 if (RT_LIKELY(pInputMutated)) 440 483 { 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); 443 486 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 444 487 *ppInputMutated = pInputMutated; … … 455 498 * Mutator callback - deletes a single byte in the input. 456 499 */ 457 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, PPRTFUZZINPUTINT ppInputMutated)500 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 458 501 { 459 502 int rc = VINF_SUCCESS; 460 PRTFUZZINPUTINT pInput = rtFuzzCtxInputPickRnd(pThis);461 if (pInput->cbInput > 1)462 {463 uint 32_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); 465 508 if (RT_LIKELY(pInputMutated)) 466 509 { 467 510 if (offDelete) 468 memcpy(&pInputMutated->abInput[0], &pInput->abInput[0], offDelete);469 if (offDelete < pInput->cbInput- 1)470 memcpy(&pInputMutated->abInput[offDelete], &p Input->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); 471 514 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 472 515 *ppInputMutated = pInputMutated; … … 483 526 * Mutator callback - deletes a byte sequence in the input. 484 527 */ 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 528 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 529 { 496 530 int rc = VINF_SUCCESS; 531 if (cbBuf > 1) 532 { 533 size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1); 534 size_t cbDel = cbBuf - cbInputMutated; 535 uint32_t offDel = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)(cbBuf - cbDel)); 536 uint8_t *pbBuf = (uint8_t *)pvBuf; 537 538 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated); 539 if (RT_LIKELY(pInputMutated)) 540 { 541 if (offDel) 542 memcpy(&pInputMutated->abInput[0], pbBuf, offDel); 543 memcpy(&pInputMutated->abInput[offDel], &pbBuf[offDel + cbDel], cbBuf - offDel - cbDel); 544 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 545 *ppInputMutated = pInputMutated; 546 } 547 else 548 rc = VERR_NO_MEMORY; 549 } 550 551 return rc; 552 } 553 554 555 static PRTFUZZCTXINT rtFuzzCtxCreateEmpty(void) 556 { 497 557 PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis)); 498 558 if (RT_LIKELY(pThis)) 499 559 { 500 pThis->u32Magic = 0xdeadc0de; /** @todo */560 pThis->u32Magic = RTFUZZCTX_MAGIC; 501 561 pThis->cRefs = 1; 502 562 pThis->TreeSeedsHigh = NULL; 503 563 pThis->cbInputMax = UINT32_MAX; 564 pThis->cInputs = 0; 504 565 pThis->fFlagsBehavioral = 0; 505 rc = RTRandAdvCreateParkMiller(&pThis->hRand); 566 RTListInit(&pThis->LstInputs); 567 568 int rc = RTRandAdvCreateParkMiller(&pThis->hRand); 506 569 if (RT_SUCCESS(rc)) 507 570 { 508 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS()); /** @todo */ 509 *phFuzzCtx = pThis; 510 return VINF_SUCCESS; 571 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS()); 572 return pThis; 511 573 } 512 574 513 575 RTMemFree(pThis); 576 } 577 578 return NULL; 579 } 580 581 582 RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx) 583 { 584 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER); 585 586 int rc = VINF_SUCCESS; 587 PRTFUZZCTXINT pThis = rtFuzzCtxCreateEmpty(); 588 if (RT_LIKELY(pThis)) 589 { 590 *phFuzzCtx = pThis; 591 return VINF_SUCCESS; 514 592 } 515 593 else … … 526 604 AssertReturn(cbState > 0, VERR_INVALID_PARAMETER); 527 605 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; 529 681 } 530 682 … … 535 687 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 536 688 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; 538 699 } 539 700 … … 573 734 AssertPtrReturn(pcbState, VERR_INVALID_POINTER); 574 735 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; 576 801 } 577 802 … … 583 808 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 584 809 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; 586 830 } 587 831 … … 797 1041 798 1042 1043 RTDECL(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 799 1053 RTDECL(int) RTFuzzCtxInputGenerate(RTFUZZCTX hFuzzCtx, PRTFUZZINPUT phFuzzInput) 800 1054 { … … 805 1059 806 1060 uint32_t cTries = 0; 1061 PRTFUZZINPUTINT pSrc = rtFuzzCtxInputPickRnd(pThis); 807 1062 do 808 1063 { 809 1064 RTFUZZCTXMUTATOR enmMutator = (RTFUZZCTXMUTATOR)RTRandAdvU32Ex(pThis->hRand, 1, RTFUZZCTXMUTATOR_LAST); 810 1065 PRTFUZZINPUTINT pInput = NULL; 811 rc = g_apfnMutators[enmMutator](pThis, &p Input);1066 rc = g_apfnMutators[enmMutator](pThis, &pSrc->abInput[0], pSrc->cbInput, &pInput); 812 1067 if ( RT_SUCCESS(rc) 813 1068 && VALID_PTR(pInput)) … … 815 1070 if (pThis->fFlagsBehavioral & RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS) 816 1071 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 1084 RTDECL(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 { 817 1100 *phFuzzInput = pInput; 818 1101 return rc; -
trunk/src/VBox/Runtime/common/fuzz/fuzzmastercmd.cpp
r72649 r72940 65 65 /** Number of processes. */ 66 66 uint32_t cProcs; 67 /** Maximum input size to generate. */68 size_t cbInputMax;69 67 /** The fuzzing observer state handle. */ 70 68 RTFUZZOBS hFuzzObs; 69 /** Flag whether fuzzing was started. */ 70 bool fStarted; 71 71 } RTFUZZRUN; 72 72 /** Pointer to a running fuzzer state. */ … … 91 91 /** Flag whether to shutdown. */ 92 92 bool fShutdown; 93 /** Flag whether to send a response along with the ACK. */94 bool fAckResponse;95 93 /** The response message. */ 96 char aszResponse[_1K];94 char *pszResponse; 97 95 } RTFUZZCMDMASTER; 98 96 /** Pointer to a fuzzing master command state. */ … … 267 265 268 266 /** 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 */ 275 static 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 /** 269 310 * Processes binary related configs for the given fuzzing run. 270 311 * … … 283 324 if (RT_LIKELY(pszBinary)) 284 325 { 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) 288 328 { 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); 293 330 if (RT_FAILURE(rc)) 294 331 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Failed to add the binary path for the fuzzing run"); … … 635 672 RTListAppend(&pThis->LstFuzzed, &pFuzzRun->NdFuzzed); 636 673 rc = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs); 637 if (RT_FAILURE(rc)) 674 if (RT_SUCCESS(rc)) 675 pFuzzRun->fStarted = true; 676 else 638 677 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to start fuzzing with %Rrc", rc); 639 678 } … … 771 810 if (RT_SUCCESS(rc)) 772 811 { 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 } 776 820 } 777 821 … … 794 838 if (RT_SUCCESS(rc)) 795 839 { 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 */ 866 static 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 797 880 if (RT_SUCCESS(rc)) 798 881 { 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"); 802 940 } 803 941 } … … 829 967 " \"FuzzedInputsHang\": %u\n" 830 968 " \"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)) 836 972 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_BUFFER_OVERFLOW, "Request error: Response data buffer overflow", rc); 837 973 } … … 869 1005 else if (!RTStrCmp(pszReq, "ResumeFuzzing")) 870 1006 rc = rtFuzzCmdMasterProcessJsonReqResume(pThis, hJsonRoot, pErrInfo); 1007 else if (!RTStrCmp(pszReq, "SaveFuzzingState")) 1008 rc = rtFuzzCmdMasterProcessJsonReqSaveState(pThis, hJsonRoot, pErrInfo); 871 1009 else if (!RTStrCmp(pszReq, "QueryStats")) 872 1010 rc = rtFuzzCmdMasterProcessJsonReqQueryStats(pThis, hJsonRoot, pErrInfo); … … 933 1071 { 934 1072 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"; 936 1075 if (pszResponse) 937 1076 { 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); 944 1088 } 945 1089 else … … 1011 1155 RTErrInfoInitStatic(&ErrInfo); 1012 1156 1013 pThis->fAckResponse = false;1014 RT_ZERO(pThis->aszResponse);1015 1157 rc = RTJsonParseFromBuf(&hJsonReq, pbReq, cbReq, &ErrInfo.Core); 1016 1158 if (RT_SUCCESS(rc)) … … 1018 1160 rc = rtFuzzCmdMasterProcessJsonReq(pThis, hJsonReq, &ErrInfo.Core); 1019 1161 if (RT_SUCCESS(rc)) 1020 rtFuzzCmdMasterTcpSendAck(hSocket, pThis-> fAckResponse ? pThis->aszResponse : NULL);1162 rtFuzzCmdMasterTcpSendAck(hSocket, pThis->pszResponse); 1021 1163 else 1022 1164 rtFuzzCmdMasterTcpSendNAck(hSocket, &ErrInfo.Core); … … 1025 1167 else 1026 1168 rtFuzzCmdMasterTcpSendNAck(hSocket, &ErrInfo.Core); 1169 1170 if (pThis->pszResponse) 1171 { 1172 RTStrFree(pThis->pszResponse); 1173 pThis->pszResponse = NULL; 1174 } 1027 1175 break; 1028 1176 } … … 1124 1272 This.pszResultsDir = NULL; 1125 1273 This.fShutdown = false; 1274 This.pszResponse = NULL; 1126 1275 1127 1276 /* Argument parsing loop. */
Note:
See TracChangeset
for help on using the changeset viewer.