Changeset 77693 in vbox for trunk/src/VBox
- Timestamp:
- Mar 13, 2019 9:24:29 PM (6 years ago)
- Location:
- trunk/src/VBox/Runtime/common/fuzz
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fuzz/fuzz-observer.cpp
r77544 r77693 112 112 /** The binary to run. */ 113 113 char *pszBinary; 114 /** The filename path of the binary. */ 115 const char *pszBinaryFilename; 114 116 /** Arguments to run the binary with, terminated by a NULL entry. */ 115 117 char **papszArgs; 118 /** The environment to use for the target. */ 119 RTENV hEnv; 120 /** Any configured sanitizers. */ 121 uint32_t fSanitizers; 122 /** Sanitizer related options set in the environment block. */ 123 char *pszSanitizerOpts; 116 124 /** Number of arguments. */ 117 125 uint32_t cArgs; … … 167 175 /** The pollset to monitor. */ 168 176 RTPOLLSET hPollSet; 177 /** The environment block to use. */ 178 RTENV hEnv; 169 179 /** The process to monitor. */ 170 180 RTPROCESS hProc; … … 335 345 pExecCtx->msExec = 0; 336 346 337 rc = RT FuzzTgtRecorderCreateNewState(pThis->hTgtRec, &pExecCtx->hTgtState);347 rc = RTEnvClone(&pExecCtx->hEnv, pThis->hEnv); 338 348 if (RT_SUCCESS(rc)) 339 349 { 340 rc = RT PollSetCreate(&pExecCtx->hPollSet);350 rc = RTFuzzTgtRecorderCreateNewState(pThis->hTgtRec, &pExecCtx->hTgtState); 341 351 if (RT_SUCCESS(rc)) 342 352 { 343 rc = RTP ipeCreate(&pExecCtx->hPipeStdoutR, &pExecCtx->hPipeStdoutW, RTPIPE_C_INHERIT_WRITE);353 rc = RTPollSetCreate(&pExecCtx->hPollSet); 344 354 if (RT_SUCCESS(rc)) 345 355 { 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); 350 AssertRC(rc); 351 352 rc = RTPipeCreate(&pExecCtx->hPipeStderrR, &pExecCtx->hPipeStderrW, RTPIPE_C_INHERIT_WRITE); 356 rc = RTPipeCreate(&pExecCtx->hPipeStdoutR, &pExecCtx->hPipeStdoutW, RTPIPE_C_INHERIT_WRITE); 353 357 if (RT_SUCCESS(rc)) 354 358 { 355 Handle.u.hPipe = pExecCtx->hPipeStderrR; 356 rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_READ, RTFUZZOBS_EXEC_CTX_POLL_ID_STDERR); 359 RTHANDLE Handle; 360 Handle.enmType = RTHANDLETYPE_PIPE; 361 Handle.u.hPipe = pExecCtx->hPipeStdoutR; 362 rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_READ, RTFUZZOBS_EXEC_CTX_POLL_ID_STDOUT); 357 363 AssertRC(rc); 358 364 359 /* Create the stdin pipe handles if not a file input. */360 if ( pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN || pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT)365 rc = RTPipeCreate(&pExecCtx->hPipeStderrR, &pExecCtx->hPipeStderrW, RTPIPE_C_INHERIT_WRITE); 366 if (RT_SUCCESS(rc)) 361 367 { 362 rc = RTPipeCreate(&pExecCtx->hPipeStdinR, &pExecCtx->hPipeStdinW, RTPIPE_C_INHERIT_READ); 368 Handle.u.hPipe = pExecCtx->hPipeStderrR; 369 rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_READ, RTFUZZOBS_EXEC_CTX_POLL_ID_STDERR); 370 AssertRC(rc); 371 372 /* Create the stdin pipe handles if not a file input. */ 373 if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN || pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT) 374 { 375 rc = RTPipeCreate(&pExecCtx->hPipeStdinR, &pExecCtx->hPipeStdinW, RTPIPE_C_INHERIT_READ); 376 if (RT_SUCCESS(rc)) 377 { 378 pExecCtx->StdinHandle.enmType = RTHANDLETYPE_PIPE; 379 pExecCtx->StdinHandle.u.hPipe = pExecCtx->hPipeStdinR; 380 381 Handle.u.hPipe = pExecCtx->hPipeStdinW; 382 rc = RTPollSetAdd(pExecCtx->hPollSet, &Handle, RTPOLL_EVT_WRITE, RTFUZZOBS_EXEC_CTX_POLL_ID_STDIN); 383 AssertRC(rc); 384 } 385 } 386 else 387 { 388 pExecCtx->StdinHandle.enmType = RTHANDLETYPE_PIPE; 389 pExecCtx->StdinHandle.u.hPipe = NIL_RTPIPE; 390 } 391 363 392 if (RT_SUCCESS(rc)) 364 393 { 365 pExecCtx->Std inHandle.enmType = RTHANDLETYPE_PIPE;366 pExecCtx->Std inHandle.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);394 pExecCtx->StdoutHandle.enmType = RTHANDLETYPE_PIPE; 395 pExecCtx->StdoutHandle.u.hPipe = pExecCtx->hPipeStdoutW; 396 pExecCtx->StderrHandle.enmType = RTHANDLETYPE_PIPE; 397 pExecCtx->StderrHandle.u.hPipe = pExecCtx->hPipeStderrW; 398 *ppExecCtx = pExecCtx; 399 return VINF_SUCCESS; 371 400 } 401 402 RTPipeClose(pExecCtx->hPipeStderrR); 403 RTPipeClose(pExecCtx->hPipeStderrW); 372 404 } 373 else 374 { 375 pExecCtx->StdinHandle.enmType = RTHANDLETYPE_PIPE; 376 pExecCtx->StdinHandle.u.hPipe = NIL_RTPIPE; 377 } 378 379 if (RT_SUCCESS(rc)) 380 { 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; 387 } 388 389 RTPipeClose(pExecCtx->hPipeStderrR); 390 RTPipeClose(pExecCtx->hPipeStderrW); 405 406 RTPipeClose(pExecCtx->hPipeStdoutR); 407 RTPipeClose(pExecCtx->hPipeStdoutW); 391 408 } 392 409 393 RTPipeClose(pExecCtx->hPipeStdoutR); 394 RTPipeClose(pExecCtx->hPipeStdoutW); 410 RTPollSetDestroy(pExecCtx->hPollSet); 395 411 } 396 412 397 RT PollSetDestroy(pExecCtx->hPollSet);398 } 399 400 RT FuzzTgtStateRelease(pExecCtx->hTgtState);413 RTFuzzTgtStateRelease(pExecCtx->hTgtState); 414 } 415 416 RTEnvDestroy(pExecCtx->hEnv); 401 417 } 402 418 … … 441 457 if (pExecCtx->hTgtState != NIL_RTFUZZTGTSTATE) 442 458 RTFuzzTgtStateRelease(pExecCtx->hTgtState); 459 RTEnvDestroy(pExecCtx->hEnv); 443 460 RTMemFree(pExecCtx); 444 461 } … … 456 473 static int rtFuzzObsExecCtxClientRun(PRTFUZZOBSINT pThis, PRTFUZZOBSEXECCTX pExecCtx, PRTPROCSTATUS pProcStat) 457 474 { 458 int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], RTENV_DEFAULT, 0 /*fFlags*/, &pExecCtx->StdinHandle,475 int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], pExecCtx->hEnv, 0 /*fFlags*/, &pExecCtx->StdinHandle, 459 476 &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, &pExecCtx->hProc); 460 477 if (RT_SUCCESS(rc)) … … 472 489 { 473 490 Assert(fEvtsRecv & RTPOLL_EVT_READ); 474 rc = RTFuzzTgtStateAppendStdoutFromPipe(pExecCtx->hTgtState, pExecCtx->hPipeStdoutR);475 AssertRC(rc);491 //rc = RTFuzzTgtStateAppendStdoutFromPipe(pExecCtx->hTgtState, pExecCtx->hPipeStdoutR); 492 //AssertRC(rc); 476 493 } 477 494 else if (idEvt == RTFUZZOBS_EXEC_CTX_POLL_ID_STDERR) 478 495 { 479 496 Assert(fEvtsRecv & RTPOLL_EVT_READ); 480 rc = RTFuzzTgtStateAppendStderrFromPipe(pExecCtx->hTgtState, pExecCtx->hPipeStderrR); 481 AssertRC(rc); 497 498 /* 499 * Can't add the stderr buffer with sancov enabled as it dumps the resulting report file path 500 * (which includes the always changing pid) to stderr... 501 */ 502 if (!(pThis->fSanitizers & RTFUZZOBS_SANITIZER_F_SANCOV)) 503 { 504 rc = RTFuzzTgtStateAppendStderrFromPipe(pExecCtx->hTgtState, pExecCtx->hPipeStderrR); 505 AssertRC(rc); 506 } 507 else 508 { 509 /* Dump to /dev/null. */ 510 char abBitBucket[_4K]; 511 size_t cbRead = 0; 512 do 513 { 514 rc = RTPipeRead(pExecCtx->hPipeStderrR, &abBitBucket[0], sizeof(abBitBucket), &cbRead); 515 } while ( RT_SUCCESS(rc) 516 && cbRead == sizeof(abBitBucket)); 517 } 482 518 } 483 519 else if (idEvt == RTFUZZOBS_EXEC_CTX_POLL_ID_STDIN) … … 508 544 rc = RTProcWait(pExecCtx->hProc, RTPROCWAIT_FLAGS_NOBLOCK, pProcStat); 509 545 if (RT_SUCCESS(rc)) 546 { 547 /* Add the coverage report to the sanitizer if enabled. */ 548 if (pThis->fSanitizers & RTFUZZOBS_SANITIZER_F_SANCOV) 549 { 550 char szSanCovReport[RTPATH_MAX]; 551 ssize_t cch = RTStrPrintf2(&szSanCovReport[0], sizeof(szSanCovReport), 552 "%s%c%s.%u.sancov", 553 pThis->pszTmpDir, RTPATH_SLASH, 554 pThis->pszBinaryFilename, pExecCtx->hProc); 555 Assert(cch > 0); RT_NOREF(cch); 556 rc = RTFuzzTgtStateAddSanCovReportFromFile(pExecCtx->hTgtState, &szSanCovReport[0]); 557 RTFileDelete(&szSanCovReport[0]); 558 } 510 559 break; 560 } 511 561 else 512 562 { … … 544 594 static int rtFuzzObsExecCtxClientRunFuzzingAware(PRTFUZZOBSINT pThis, PRTFUZZOBSEXECCTX pExecCtx, PRTPROCSTATUS pProcStat) 545 595 { 546 int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], RTENV_DEFAULT, 0 /*fFlags*/, &pExecCtx->StdinHandle,596 int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], pExecCtx->hEnv, 0 /*fFlags*/, &pExecCtx->StdinHandle, 547 597 &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, &pExecCtx->hProc); 548 598 if (RT_SUCCESS(rc)) … … 1001 1051 1002 1052 1053 /** 1054 * Sets up any configured sanitizers to cooperate with the observer. 1055 * 1056 * @returns IPRT status code. 1057 * @param pThis The internal fuzzing observer state. 1058 */ 1059 static int rtFuzzObsSetupSanitizerCfg(PRTFUZZOBSINT pThis) 1060 { 1061 int rc = VINF_SUCCESS; 1062 bool fSep = false; 1063 1064 if (pThis->fSanitizers & RTFUZZOBS_SANITIZER_F_ASAN) 1065 { 1066 /* 1067 * Need to set abort_on_error=1 in ASAN_OPTIONS or 1068 * the sanitizer will call exit() instead of abort() and we 1069 * don't catch invalid memory accesses. 1070 */ 1071 rc = RTStrAAppend(&pThis->pszSanitizerOpts, "abort_on_error=1"); 1072 fSep = true; 1073 } 1074 1075 if ( RT_SUCCESS(rc) 1076 && (pThis->fSanitizers & RTFUZZOBS_SANITIZER_F_SANCOV)) 1077 { 1078 /* 1079 * The coverage sanitizer will dump coverage information into a file 1080 * on process exit. Need to configure the directory where to dump it. 1081 */ 1082 char aszSanCovCfg[_4K]; 1083 ssize_t cch = RTStrPrintf2(&aszSanCovCfg[0], sizeof(aszSanCovCfg), 1084 "%scoverage=1:coverage_dir=%s", 1085 fSep ? ":" : "", pThis->pszTmpDir); 1086 if (cch > 0) 1087 rc = RTStrAAppend(&pThis->pszSanitizerOpts, &aszSanCovCfg[0]); 1088 else 1089 rc = VERR_BUFFER_OVERFLOW; 1090 fSep = true; 1091 } 1092 1093 if ( RT_SUCCESS(rc) 1094 && pThis->pszSanitizerOpts) 1095 { 1096 /* Add it to the environment. */ 1097 if (pThis->hEnv == RTENV_DEFAULT) 1098 { 1099 /* Clone the environment to keep the default one untouched. */ 1100 rc = RTEnvClone(&pThis->hEnv, RTENV_DEFAULT); 1101 } 1102 if (RT_SUCCESS(rc)) 1103 rc = RTEnvSetEx(pThis->hEnv, "ASAN_OPTIONS", pThis->pszSanitizerOpts); 1104 } 1105 1106 return rc; 1107 } 1108 1109 1003 1110 RTDECL(int) RTFuzzObsCreate(PRTFUZZOBS phFuzzObs, RTFUZZCTXTYPE enmType) 1004 1111 { … … 1009 1116 if (RT_LIKELY(pThis)) 1010 1117 { 1011 pThis->pszBinary = NULL; 1012 pThis->papszArgs = NULL; 1013 pThis->msWaitMax = 1000; 1014 pThis->hThreadGlobal = NIL_RTTHREAD; 1015 pThis->hEvtGlobal = NIL_RTSEMEVENT; 1016 pThis->bmEvt = 0; 1017 pThis->cThreads = 0; 1018 pThis->paObsThreads = NULL; 1019 pThis->tsLastStats = RTTimeMilliTS(); 1118 pThis->pszBinary = NULL; 1119 pThis->pszBinaryFilename = NULL; 1120 pThis->papszArgs = NULL; 1121 pThis->hEnv = RTENV_DEFAULT; 1122 pThis->msWaitMax = 1000; 1123 pThis->hThreadGlobal = NIL_RTTHREAD; 1124 pThis->hEvtGlobal = NIL_RTSEMEVENT; 1125 pThis->bmEvt = 0; 1126 pThis->cThreads = 0; 1127 pThis->paObsThreads = NULL; 1128 pThis->tsLastStats = RTTimeMilliTS(); 1020 1129 pThis->Stats.cFuzzedInputsPerSec = 0; 1021 1130 pThis->Stats.cFuzzedInputs = 0; … … 1065 1174 if (pThis->pszBinary) 1066 1175 RTStrFree(pThis->pszBinary); 1176 if (pThis->pszSanitizerOpts) 1177 RTStrFree(pThis->pszSanitizerOpts); 1178 if (pThis->hEnv != RTENV_DEFAULT) 1179 { 1180 RTEnvDestroy(pThis->hEnv); 1181 pThis->hEnv = RTENV_DEFAULT; 1182 } 1067 1183 RTFuzzTgtRecorderRelease(pThis->hTgtRec); 1068 1184 RTFuzzCtxRelease(pThis->hFuzzCtx); … … 1148 1264 if (RT_UNLIKELY(!pThis->pszBinary)) 1149 1265 rc = VERR_NO_STR_MEMORY; 1266 else 1267 pThis->pszBinaryFilename = RTPathFilename(pThis->pszBinary); 1150 1268 return rc; 1151 1269 } … … 1209 1327 1210 1328 1329 RTDECL(int) RTFuzzObsSetTestBinaryEnv(RTFUZZOBS hFuzzObs, RTENV hEnv) 1330 { 1331 PRTFUZZOBSINT pThis = hFuzzObs; 1332 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1333 1334 pThis->hEnv = hEnv; 1335 return VINF_SUCCESS; 1336 } 1337 1338 1339 RTDECL(int) RTFuzzObsSetTestBinarySanitizers(RTFUZZOBS hFuzzObs, uint32_t fSanitizers) 1340 { 1341 PRTFUZZOBSINT pThis = hFuzzObs; 1342 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1343 1344 pThis->fSanitizers = fSanitizers; 1345 return VINF_SUCCESS; 1346 } 1347 1348 1349 RTDECL(int) RTFuzzObsSetTestBinaryTimeout(RTFUZZOBS hFuzzObs, RTMSINTERVAL msTimeoutMax) 1350 { 1351 PRTFUZZOBSINT pThis = hFuzzObs; 1352 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1353 1354 pThis->msWaitMax = msTimeoutMax; 1355 return VINF_SUCCESS; 1356 } 1357 1358 1211 1359 RTDECL(int) RTFuzzObsExecStart(RTFUZZOBS hFuzzObs, uint32_t cProcs) 1212 1360 { … … 1222 1370 cProcs = RT_MIN(RTMpGetPresentCoreCount(), sizeof(uint64_t) * 8); 1223 1371 1224 /* Spin up the worker threads first. */ 1225 rc = rtFuzzObsWorkersCreate(pThis, cProcs); 1372 rc = rtFuzzObsSetupSanitizerCfg(pThis); 1226 1373 if (RT_SUCCESS(rc)) 1227 1374 { 1228 /* Spin up the global thread. */ 1229 rc = rtFuzzObsMasterCreate(pThis); 1375 /* Spin up the worker threads first. */ 1376 rc = rtFuzzObsWorkersCreate(pThis, cProcs); 1377 if (RT_SUCCESS(rc)) 1378 { 1379 /* Spin up the global thread. */ 1380 rc = rtFuzzObsMasterCreate(pThis); 1381 } 1230 1382 } 1231 1383 -
trunk/src/VBox/Runtime/common/fuzz/fuzz-target-recorder.cpp
r77547 r77693 35 35 #include <iprt/assert.h> 36 36 #include <iprt/avl.h> 37 #include <iprt/crc.h> 37 38 #include <iprt/ctype.h> 38 39 #include <iprt/err.h> … … 76 77 /** Node for the list of states. */ 77 78 RTLISTNODE NdStates; 79 /** Checksum for the state. */ 80 uint64_t uChkSum; 78 81 /** Magic identifying the structure. */ 79 82 uint32_t u32Magic; … … 90 93 /** The stderr data buffer. */ 91 94 RTFUZZTGTSTDOUTERRBUF StdErrBuf; 95 /** Coverage report buffer. */ 96 void *pvCovReport; 97 /** Size of the coverage report in bytes. */ 98 size_t cbCovReport; 99 /** Number of traced edges. */ 100 size_t cEdges; 92 101 } RTFUZZTGTSTATEINT; 93 102 /** Pointer to an internal fuzzed target state. */ … … 100 109 typedef struct RTFUZZTGTRECNODE 101 110 { 102 /** The AVL tree core (keyed by stdout/stderr buffer sizes). */111 /** The AVL tree core (keyed by checksum). */ 103 112 AVLU64NODECORE Core; 104 113 /** The list anchor for the individual states. */ … … 107 116 /** Pointer to a recorder states node. */ 108 117 typedef RTFUZZTGTRECNODE *PRTFUZZTGTRECNODE; 118 119 120 /** 121 * Edge information node. 122 */ 123 typedef struct RTFUZZTGTEDGE 124 { 125 /** The AVL tree core (keyed by offset). */ 126 AVLU64NODECORE Core; 127 /** Number of times the edge was hit. */ 128 volatile uint64_t cHits; 129 } RTFUZZTGTEDGE; 130 /** Pointer to a edge information node. */ 131 typedef RTFUZZTGTEDGE *PRTFUZZTGTEDGE; 109 132 110 133 … … 122 145 /** The AVL tree for indexing the recorded state (keyed by stdout/stderr buffer size). */ 123 146 AVLU64TREE TreeStates; 147 /** Semaphore protecting the edges tree. */ 148 RTSEMRW hSemRwEdges; 149 /** The AVL tree for discovered edges when coverage reports are collected. */ 150 AVLU64TREE TreeEdges; 151 /** Number of edges discovered so far. */ 152 volatile uint64_t cEdges; 153 /** The discovered offset width. */ 154 volatile uint32_t cbCovOff; 124 155 } RTFUZZTGTRECINT; 156 157 158 /** SanCov magic for 64bit offsets. */ 159 #define SANCOV_MAGIC_64 UINT64_C(0xc0bfffffffffff64) 160 /** SanCov magic for 32bit offsets. */ 161 #define SANCOV_MAGIC_32 UINT64_C(0xc0bfffffffffff32) 125 162 126 163 … … 200 237 201 238 /** 239 * Scans the given target state for newly discovered edges in the coverage report. 240 * 241 * @returns IPRT status code. 242 * @param pThis The fuzzer target recorder instance. 243 * @param pTgtState The target state to check. 244 */ 245 static int rtFuzzTgtRecScanStateForNewEdges(PRTFUZZTGTRECINT pThis, PRTFUZZTGTSTATEINT pTgtState) 246 { 247 int rc = VINF_SUCCESS; 248 249 if (pTgtState->pvCovReport) 250 { 251 rc = RTSemRWRequestRead(pThis->hSemRwEdges, RT_INDEFINITE_WAIT); AssertRC(rc); 252 253 uint32_t cbCovOff = ASMAtomicReadU32(&pThis->cbCovOff); 254 Assert(cbCovOff != 0); 255 256 uint8_t *pbCovCur = (uint8_t *)pTgtState->pvCovReport; 257 size_t cEdgesLeft = pTgtState->cbCovReport / cbCovOff; 258 while (cEdgesLeft) 259 { 260 uint64_t offCur = cbCovOff == sizeof(uint64_t) 261 ? *(uint64_t *)pbCovCur 262 : *(uint32_t *)pbCovCur; 263 264 PRTFUZZTGTEDGE pEdge = (PRTFUZZTGTEDGE)RTAvlU64Get(&pThis->TreeEdges, offCur); 265 if (!pEdge) 266 { 267 /* New edge discovered, allocate and add. */ 268 rc = RTSemRWReleaseRead(pThis->hSemRwEdges); AssertRC(rc); 269 270 pEdge = (PRTFUZZTGTEDGE)RTMemAllocZ(sizeof(RTFUZZTGTEDGE)); 271 if (RT_LIKELY(pEdge)) 272 { 273 pEdge->Core.Key = offCur; 274 pEdge->cHits = 1; 275 rc = RTSemRWRequestWrite(pThis->hSemRwEdges, RT_INDEFINITE_WAIT); AssertRC(rc); 276 277 bool fIns = RTAvlU64Insert(&pThis->TreeEdges, &pEdge->Core); 278 if (!fIns) 279 { 280 /* Someone raced us, free and query again. */ 281 RTMemFree(pEdge); 282 pEdge = (PRTFUZZTGTEDGE)RTAvlU64Get(&pThis->TreeEdges, offCur); 283 AssertPtr(pEdge); 284 285 ASMAtomicIncU64(&pEdge->cHits); 286 } 287 else 288 ASMAtomicIncU64(&pThis->cEdges); 289 290 rc = RTSemRWReleaseWrite(pThis->hSemRwEdges); AssertRC(rc); 291 rc = RTSemRWRequestRead(pThis->hSemRwEdges, RT_INDEFINITE_WAIT); AssertRC(rc); 292 } 293 else 294 { 295 rc = RTSemRWRequestRead(pThis->hSemRwEdges, RT_INDEFINITE_WAIT); 296 AssertRC(rc); 297 298 rc = VERR_NO_MEMORY; 299 break; 300 } 301 } 302 else 303 ASMAtomicIncU64(&pEdge->cHits); 304 305 pbCovCur += cbCovOff; 306 cEdgesLeft--; 307 } 308 309 rc = RTSemRWReleaseRead(pThis->hSemRwEdges); AssertRC(rc); 310 } 311 312 return rc; 313 } 314 315 316 /** 202 317 * Destorys the given fuzzer target recorder freeing all allocated resources. 203 318 * … … 212 327 213 328 /** 214 * Dest orys the given fuzzer target recorderfreeing all allocated resources.329 * Destroys the given fuzzer target state freeing all allocated resources. 215 330 * 216 331 * @returns nothing. … … 235 350 pThis->cRefs = 1; 236 351 pThis->TreeStates = NULL; 352 pThis->TreeEdges = NULL; 353 pThis->cbCovOff = 0; 237 354 238 355 rc = RTSemRWCreate(&pThis->hSemRwStates); 239 356 if (RT_SUCCESS(rc)) 240 357 { 241 *phFuzzTgtRec = pThis; 242 return VINF_SUCCESS; 358 rc = RTSemRWCreate(&pThis->hSemRwEdges); 359 if (RT_SUCCESS(rc)) 360 { 361 *phFuzzTgtRec = pThis; 362 return VINF_SUCCESS; 363 } 364 365 RTSemRWDestroy(pThis->hSemRwStates); 243 366 } 244 367 … … 339 462 pThis->StdOutBuf.cbBuf = 0; 340 463 pThis->StdErrBuf.cbBuf = 0; 464 if (pThis->pvCovReport) 465 RTMemFree(pThis->pvCovReport); 466 pThis->pvCovReport = NULL; 341 467 pThis->fFinalized = false; 342 468 return VINF_SUCCESS; … … 349 475 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 350 476 351 /* 352 * As we key both the stdout and stderr sizes in one 64bit 353 * AVL tree core we only have 32bit for each and refuse buffers 354 * exceeding this size (very unlikely for now). 355 */ 356 if (RT_UNLIKELY( pThis->StdOutBuf.cbBuf > UINT32_MAX 357 || pThis->StdErrBuf.cbBuf > UINT32_MAX)) 358 return VERR_BUFFER_OVERFLOW; 359 477 /* Create the checksum. */ 478 uint64_t uChkSum = RTCrc64Start(); 479 if (pThis->StdOutBuf.cbBuf) 480 uChkSum = RTCrc64Process(uChkSum, pThis->StdOutBuf.pbBase, pThis->StdOutBuf.cbBuf); 481 if (pThis->StdErrBuf.cbBuf) 482 uChkSum = RTCrc64Process(uChkSum, pThis->StdErrBuf.pbBase, pThis->StdErrBuf.cbBuf); 483 if (pThis->pvCovReport) 484 uChkSum = RTCrc64Process(uChkSum, pThis->pvCovReport, pThis->cbCovReport); 485 486 pThis->uChkSum = RTCrc64Finish(uChkSum); 360 487 pThis->fFinalized = true; 361 488 return VINF_SUCCESS; … … 376 503 377 504 PRTFUZZTGTRECINT pTgtRec = pThis->pTgtRec; 378 uint64_t uKey = ((uint64_t)pThis->StdOutBuf.cbBuf << 32) | pThis->StdErrBuf.cbBuf;379 505 380 506 /* Try to find a node matching the stdout and sterr sizes first. */ 381 507 int rc = RTSemRWRequestRead(pTgtRec->hSemRwStates, RT_INDEFINITE_WAIT); AssertRC(rc); 382 PRTFUZZTGTRECNODE pNode = (PRTFUZZTGTRECNODE)RTAvlU64Get(&pTgtRec->TreeStates, uKey);508 PRTFUZZTGTRECNODE pNode = (PRTFUZZTGTRECNODE)RTAvlU64Get(&pTgtRec->TreeStates, pThis->uChkSum); 383 509 if (pNode) 384 510 { … … 393 519 || !memcmp(pThis->StdOutBuf.pbBase, pIt->StdOutBuf.pbBase, pThis->StdOutBuf.cbBuf)) 394 520 && ( !pThis->StdErrBuf.cbBuf 395 || !memcmp(pThis->StdErrBuf.pbBase, pIt->StdErrBuf.pbBase, pThis->StdErrBuf.cbBuf))) 521 || !memcmp(pThis->StdErrBuf.pbBase, pIt->StdErrBuf.pbBase, pThis->StdErrBuf.cbBuf)) 522 && ( pThis->cbCovReport != pIt->cbCovReport 523 || ( pThis->cbCovReport > 0 524 && !memcmp(pThis->pvCovReport, pIt->pvCovReport, pThis->cbCovReport)))) 396 525 { 397 526 fMatchFound = true; … … 419 548 if (RT_LIKELY(pNode)) 420 549 { 421 pNode->Core.Key = uKey;550 pNode->Core.Key = pThis->uChkSum; 422 551 RTListInit(&pNode->LstStates); 423 552 RTListAppend(&pNode->LstStates, &pThis->NdStates); … … 428 557 /* Someone raced us, get the new node and append there. */ 429 558 RTMemFree(pNode); 430 pNode = (PRTFUZZTGTRECNODE)RTAvlU64Get(&pTgtRec->TreeStates, uKey);559 pNode = (PRTFUZZTGTRECNODE)RTAvlU64Get(&pTgtRec->TreeStates, pThis->uChkSum); 431 560 AssertPtr(pNode); 432 561 RTListAppend(&pNode->LstStates, &pThis->NdStates); … … 439 568 } 440 569 570 if ( RT_SUCCESS(rc) 571 && pThis->fInRecSet) 572 rc = rtFuzzTgtRecScanStateForNewEdges(pTgtRec, pThis); 573 441 574 return rc; 442 575 } … … 484 617 } 485 618 619 620 RTDECL(int) RTFuzzTgtStateAddSanCovReportFromFile(RTFUZZTGTSTATE hFuzzTgtState, const char *pszFilename) 621 { 622 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState; 623 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 624 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 625 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); 626 627 uint8_t *pbSanCov = NULL; 628 size_t cbSanCov = 0; 629 int rc = RTFileReadAll(pszFilename, (void **)&pbSanCov, &cbSanCov); 630 if (RT_SUCCESS(rc)) 631 { 632 /* Check for the magic identifying whether the offsets are 32bit or 64bit. */ 633 if ( cbSanCov >= sizeof(uint64_t) 634 && ( *(uint64_t *)pbSanCov == SANCOV_MAGIC_64 635 || *(uint64_t *)pbSanCov == SANCOV_MAGIC_32)) 636 { 637 uint32_t cbCovOff = sizeof(uint32_t); 638 if (*(uint64_t *)pbSanCov == SANCOV_MAGIC_64) 639 cbCovOff = sizeof(uint64_t); 640 641 uint32_t cbCovDet = ASMAtomicReadU32(&pThis->pTgtRec->cbCovOff); 642 if (!cbCovDet) 643 { 644 /* Set the detected offset width. */ 645 if (!ASMAtomicCmpXchgU32(&pThis->pTgtRec->cbCovOff, cbCovOff, 0)) 646 { 647 /* Someone raced us, check again. */ 648 cbCovDet = ASMAtomicReadU32(&pThis->pTgtRec->cbCovOff); 649 Assert(cbCovDet != 0); 650 } 651 else 652 cbCovDet = cbCovOff; 653 } 654 655 if (cbCovDet == cbCovOff) 656 { 657 /* 658 * Just copy the offsets into the state for now. Now further analysis 659 * is happening right now, just checking whether the content changed for 660 * the states.to spot newly discovered edges. 661 */ 662 pThis->cbCovReport = cbSanCov - sizeof(uint64_t); 663 pThis->pvCovReport = RTMemDup(pbSanCov + sizeof(uint64_t), pThis->cbCovReport); 664 if (!pThis->pvCovReport) 665 { 666 pThis->cbCovReport = 0; 667 rc = VERR_NO_MEMORY; 668 } 669 } 670 else 671 rc = VERR_INVALID_STATE; /* Mixing 32bit and 64bit offsets shouldn't happen, is not supported. */ 672 } 673 else 674 rc = VERR_INVALID_STATE; 675 RTFileReadAllFree(pbSanCov, cbSanCov); 676 } 677 return rc; 678 } 679 -
trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp
r77658 r77693 1121 1121 { 1122 1122 int rc = VINF_SUCCESS; 1123 if (pMutationParent->cbInput > offStart) 1123 if ( pMutationParent->cbInput > offStart 1124 && pMutationParent->cbInput > 1) 1124 1125 { 1125 1126 size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, offStart, pMutationParent->cbInput - 1); … … 1992 1993 uint64_t offStart = 0; 1993 1994 if (!(pMutator->fFlags & RTFUZZMUTATOR_F_END_OF_BUF)) 1994 offStart = RTRandAdvU64Ex(pThis->hRand, 0, pMutationParent->cbInput );1995 offStart = RTRandAdvU64Ex(pThis->hRand, 0, pMutationParent->cbInput - 1); 1995 1996 else 1996 1997 offStart = pMutationParent->cbInput; -
trunk/src/VBox/Runtime/common/fuzz/fuzzmastercmd.cpp
r77659 r77693 37 37 #include <iprt/buildconfig.h> 38 38 #include <iprt/ctype.h> 39 #include <iprt/env.h> 39 40 #include <iprt/err.h> 40 41 #include <iprt/file.h> … … 50 51 #include <iprt/tcp.h> 51 52 #include <iprt/thread.h> 53 #include <iprt/time.h> 52 54 #include <iprt/vfs.h> 53 55 #include <iprt/zip.h> … … 69 71 /** Flag whether fuzzing was started. */ 70 72 bool fStarted; 73 /** Time when this run was created. */ 74 RTTIME TimeCreated; 75 /** Millisecond timestamp when the run was created. */ 76 uint64_t tsCreatedMs; 71 77 } RTFUZZRUN; 72 78 /** Pointer to a running fuzzer state. */ … … 407 413 RTJsonValueRelease(hJsonValArgArray); 408 414 } 415 416 return rc; 417 } 418 419 420 /** 421 * Processes process environment related configs for the given fuzzing run. 422 * 423 * @returns IPRT status code. 424 * @param pFuzzRun The fuzzing run. 425 * @param hJsonRoot The root node of the JSON request. 426 * @param pErrInfo Where to store the error information on failure, optional. 427 */ 428 static int rtFuzzCmdMasterFuzzRunProcessEnvironment(PRTFUZZRUN pFuzzRun, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo) 429 { 430 RTJSONVAL hJsonValEnv; 431 int rc = RTJsonValueQueryByName(hJsonRoot, "Env", &hJsonValEnv); 432 if (RT_SUCCESS(rc)) 433 { 434 bool fReplaceEnv = false; /* false means to append everything to the default block. */ 435 436 rc = RTJsonValueQueryBooleanByName(hJsonRoot, "EnvReplace", &fReplaceEnv); 437 if ( RT_SUCCESS(rc) 438 || rc == VERR_NOT_FOUND) 439 { 440 RTJSONIT hEnvIt; 441 RTENV hEnv = NULL; 442 443 if (fReplaceEnv) 444 rc = RTEnvCreate(&hEnv); 445 else 446 rc = RTEnvClone(&hEnv, RTENV_DEFAULT); 447 448 if (RT_SUCCESS(rc)) 449 { 450 rc = RTJsonIteratorBeginArray(hJsonValEnv, &hEnvIt); 451 if (RT_SUCCESS(rc)) 452 { 453 do 454 { 455 RTJSONVAL hVal; 456 rc = RTJsonIteratorQueryValue(hEnvIt, &hVal, NULL); 457 if (RT_SUCCESS(rc)) 458 { 459 const char *pszVar = RTJsonValueGetString(hVal); 460 if (RT_LIKELY(pszVar)) 461 rc = RTEnvPutEx(hEnv, pszVar); 462 RTJsonValueRelease(hVal); 463 } 464 rc = RTJsonIteratorNext(hEnvIt); 465 } while (RT_SUCCESS(rc)); 466 467 if ( rc == VERR_JSON_IS_EMPTY 468 || rc == VERR_JSON_ITERATOR_END) 469 rc = VINF_SUCCESS; 470 else 471 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to parse environment"); 472 473 RTJsonIteratorFree(hEnvIt); 474 } 475 else if (rc == VERR_JSON_IS_EMPTY) 476 rc = VINF_SUCCESS; 477 else 478 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: \"Environment\" is not an array"); 479 480 if (RT_SUCCESS(rc)) 481 { 482 rc = RTFuzzObsSetTestBinaryEnv(pFuzzRun->hFuzzObs, hEnv); 483 AssertRC(rc); 484 } 485 else if (hEnv) 486 RTEnvDestroy(hEnv); 487 } 488 else 489 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to create environment block"); 490 } 491 else 492 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query \"EnvReplace\""); 493 494 RTJsonValueRelease(hJsonValEnv); 495 } 496 else if (rc == VERR_NOT_FOUND) 497 rc = VINF_SUCCESS; /* Just keep using the default environment. */ 498 else 499 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query the \"Environment\""); 500 501 return rc; 502 } 503 504 505 /** 506 * Processes process environment related configs for the given fuzzing run. 507 * 508 * @returns IPRT status code. 509 * @param pFuzzRun The fuzzing run. 510 * @param hJsonRoot The root node of the JSON request. 511 * @param pErrInfo Where to store the error information on failure, optional. 512 */ 513 static int rtFuzzCmdMasterFuzzRunProcessSanitizers(PRTFUZZRUN pFuzzRun, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo) 514 { 515 RTJSONVAL hJsonValSan; 516 int rc = RTJsonValueQueryByName(hJsonRoot, "Sanitizers", &hJsonValSan); 517 if (RT_SUCCESS(rc)) 518 { 519 uint32_t fSanitizers = 0; 520 RTJSONIT hSanIt; 521 rc = RTJsonIteratorBeginArray(hJsonValSan, &hSanIt); 522 if (RT_SUCCESS(rc)) 523 { 524 do 525 { 526 RTJSONVAL hVal; 527 rc = RTJsonIteratorQueryValue(hSanIt, &hVal, NULL); 528 if (RT_SUCCESS(rc)) 529 { 530 const char *pszSan = RTJsonValueGetString(hVal); 531 if (!RTStrICmp(pszSan, "Asan")) 532 fSanitizers |= RTFUZZOBS_SANITIZER_F_ASAN; 533 else if (!RTStrICmp(pszSan, "SanCov")) 534 fSanitizers |= RTFUZZOBS_SANITIZER_F_SANCOV; 535 else 536 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_NOT_FOUND, "JSON request malformed: The sanitizer '%s' is not known", pszSan); 537 RTJsonValueRelease(hVal); 538 } 539 rc = RTJsonIteratorNext(hSanIt); 540 } while (RT_SUCCESS(rc)); 541 542 if ( rc == VERR_JSON_IS_EMPTY 543 || rc == VERR_JSON_ITERATOR_END) 544 rc = VINF_SUCCESS; 545 else 546 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to parse sanitizers"); 547 548 RTJsonIteratorFree(hSanIt); 549 } 550 else if (rc == VERR_JSON_IS_EMPTY) 551 rc = VINF_SUCCESS; 552 else 553 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: \"Sanitizers\" is not an array"); 554 555 if (RT_SUCCESS(rc)) 556 { 557 rc = RTFuzzObsSetTestBinarySanitizers(pFuzzRun->hFuzzObs, fSanitizers); 558 AssertRC(rc); 559 } 560 561 RTJsonValueRelease(hJsonValSan); 562 } 563 else if (rc == VERR_NOT_FOUND) 564 rc = VINF_SUCCESS; /* Just keep using the defaults. */ 565 else 566 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query the \"Sanitizers\""); 409 567 410 568 return rc; … … 614 772 if (RT_SUCCESS(rc)) 615 773 rc = rtFuzzCmdMasterFuzzRunProcessCfgU32Def(&pFuzzRun->cProcs, "FuzzingProcs", hJsonRoot, 0, pErrInfo); 774 if (RT_SUCCESS(rc)) 775 { 776 uint32_t msTimeoutMax = 0; 777 rc = rtFuzzCmdMasterFuzzRunProcessCfgU32Def(&msTimeoutMax, "TimeoutMax", hJsonRoot, 1000, pErrInfo); 778 if (RT_SUCCESS(rc)) 779 rc = RTFuzzObsSetTestBinaryTimeout(pFuzzRun->hFuzzObs, msTimeoutMax); 780 } 616 781 617 782 return rc; … … 694 859 rc = rtFuzzCmdMasterFuzzRunProcessArgCfg(pFuzzRun, hJsonRoot, pErrInfo); 695 860 if (RT_SUCCESS(rc)) 861 rc = rtFuzzCmdMasterFuzzRunProcessEnvironment(pFuzzRun, hJsonRoot, pErrInfo); 862 if (RT_SUCCESS(rc)) 696 863 rc = rtFuzzCmdMasterFuzzRunProcessInputSeeds(pFuzzRun, hJsonRoot, pErrInfo); 697 864 if (RT_SUCCESS(rc)) 698 865 rc = rtFuzzCmdMasterFuzzRunProcessMiscCfg(pFuzzRun, hJsonRoot, pErrInfo); 866 if (RT_SUCCESS(rc)) 867 rc = rtFuzzCmdMasterFuzzRunProcessSanitizers(pFuzzRun, hJsonRoot, pErrInfo); 699 868 if (RT_SUCCESS(rc)) 700 869 rc = rtFuzzCmdMasterFuzzRunSetupDirectories(pThis, pFuzzRun, pErrInfo); … … 706 875 rc = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs); 707 876 if (RT_SUCCESS(rc)) 877 { 878 RTTIMESPEC TimeSpec; 879 RTTimeNow(&TimeSpec); 880 RTTimeLocalExplode(&pFuzzRun->TimeCreated, &TimeSpec); 881 pFuzzRun->tsCreatedMs = RTTimeMilliTS(); 708 882 pFuzzRun->fStarted = true; 883 } 709 884 else 710 885 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to start fuzzing with %Rrc", rc); … … 996 1171 { 997 1172 const char s_szStatsFmt[] = "%s{ \n" 998 "%s \"Id\": %s\n" 1173 "%s \"Id\": \"%s\"\n" 1174 "%s \"TimeCreated\": \"%s\"\n" 1175 "%s \"UptimeSec\": %llu\n" 999 1176 "%s \"FuzzedInputsPerSec\": %u\n" 1000 1177 "%s \"FuzzedInputs\": %u\n" … … 1004 1181 "%s \"CorpusSize\": %llu\n" 1005 1182 "%s}%s\n"; 1006 char achStats[_4K]; RT_ZERO(achStats); 1007 ssize_t cchStats = RTStrPrintf2(&achStats[0], sizeof(achStats), 1008 s_szStatsFmt, pszIndent, 1009 pszIndent, pFuzzRun->pszId, 1010 pszIndent, ObsStats.cFuzzedInputsPerSec, 1011 pszIndent, ObsStats.cFuzzedInputs, 1012 pszIndent, ObsStats.cFuzzedInputsHang, 1013 pszIndent, ObsStats.cFuzzedInputsCrash, 1014 pszIndent, CtxStats.cbMemory, 1015 pszIndent, CtxStats.cMutations, 1016 pszIndent, fLast ? "" : ","); 1017 if (RT_LIKELY(cchStats > 0)) 1018 { 1019 rc = RTStrAAppend(&pThis->pszResponse, &achStats[0]); 1020 if (RT_FAILURE(rc)) 1021 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to build statistics response", rc); 1183 char aszTime[_1K]; RT_ZERO(aszTime); 1184 char aszStats[_4K]; RT_ZERO(aszStats); 1185 1186 if (RTTimeToString(&pFuzzRun->TimeCreated, aszTime, sizeof(aszTime))) 1187 { 1188 ssize_t cchStats = RTStrPrintf2(&aszStats[0], sizeof(aszStats), 1189 s_szStatsFmt, pszIndent, 1190 pszIndent, pFuzzRun->pszId, 1191 pszIndent, aszTime, 1192 pszIndent, (RTTimeMilliTS() - pFuzzRun->tsCreatedMs) / RT_MS_1SEC_64, 1193 pszIndent, ObsStats.cFuzzedInputsPerSec, 1194 pszIndent, ObsStats.cFuzzedInputs, 1195 pszIndent, ObsStats.cFuzzedInputsHang, 1196 pszIndent, ObsStats.cFuzzedInputsCrash, 1197 pszIndent, CtxStats.cbMemory, 1198 pszIndent, CtxStats.cMutations, 1199 pszIndent, fLast ? "" : ","); 1200 if (RT_LIKELY(cchStats > 0)) 1201 { 1202 rc = RTStrAAppend(&pThis->pszResponse, &aszStats[0]); 1203 if (RT_FAILURE(rc)) 1204 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to build statistics response", rc); 1205 } 1206 else 1207 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_BUFFER_OVERFLOW, "Request error: Response data buffer overflow"); 1022 1208 } 1023 1209 else 1024 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_BUFFER_OVERFLOW, "Request error: Response data buffer overflow", rc);1210 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_BUFFER_OVERFLOW, "Request error: Buffer overflow conerting time to string"); 1025 1211 } 1026 1212 else
Note:
See TracChangeset
for help on using the changeset viewer.