VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/fuzz/fuzz-observer.cpp@ 72437

Last change on this file since 72437 was 72437, checked in by vboxsync, 7 years ago

Runtime/RTFuzz: build fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1/* $Id: fuzz-observer.cpp 72437 2018-06-04 21:16:02Z vboxsync $ */
2/** @file
3 * IPRT Fuzzing framework API (Fuzz).
4 */
5
6/*
7 * Copyright (C) 2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/asm.h>
32#include <iprt/assert.h>
33#include <iprt/cdefs.h>
34#include <iprt/ctype.h>
35#include <iprt/err.h>
36#include <iprt/env.h>
37#include <iprt/file.h>
38#include <iprt/fuzz.h>
39#include <iprt/path.h>
40#include <iprt/pipe.h>
41#include <iprt/process.h>
42#include <iprt/md5.h>
43#include <iprt/mem.h>
44#include <iprt/mp.h>
45#include <iprt/semaphore.h>
46#include <iprt/stream.h>
47#include <iprt/string.h>
48#include <iprt/time.h>
49#include <iprt/thread.h>
50
51
52/*********************************************************************************************************************************
53* Defined Constants And Macros *
54*********************************************************************************************************************************/
55
56
57/*********************************************************************************************************************************
58* Structures and Typedefs *
59*********************************************************************************************************************************/
60
61/** Pointer to the internal fuzzing observer state. */
62typedef struct RTFUZZOBSINT *PRTFUZZOBSINT;
63
64
65/**
66 * Observer thread state for one process.
67 */
68typedef struct RTFUZZOBSTHRD
69{
70 /** The thread handle. */
71 RTTHREAD hThrd;
72 /** The observer ID. */
73 uint32_t idObs;
74 /** Flag whether to shutdown. */
75 volatile bool fShutdown;
76 /** Pointer to te global observer state. */
77 PRTFUZZOBSINT pFuzzObs;
78 /** Current fuzzer input. */
79 RTFUZZINPUT hFuzzInput;
80 /** Flag whether to keep the input. */
81 bool fKeepInput;
82 /** Flag whether a new input is waiting. */
83 volatile bool fNewInput;
84} RTFUZZOBSTHRD;
85/** Pointer to an observer thread state. */
86typedef RTFUZZOBSTHRD *PRTFUZZOBSTHRD;
87
88
89/**
90 * Internal fuzzing observer state.
91 */
92typedef struct RTFUZZOBSINT
93{
94 /** The fuzzing context used for this observer. */
95 RTFUZZCTX hFuzzCtx;
96 /** Temp directory for input files. */
97 char *pszTmpDir;
98 /** The binary to run. */
99 char *pszBinary;
100 /** Arguments to run the binary with, terminated by a NULL entry. */
101 char **papszArgs;
102 /** Number of arguments. */
103 uint32_t cArgs;
104 /** Flags controlling how the binary is executed. */
105 uint32_t fFlags;
106 /** Flag whether to shutdown the master and all workers. */
107 volatile bool fShutdown;
108 /** Global observer thread handle. */
109 RTTHREAD hThrdGlobal;
110 /** The event semaphore handle for the global observer thread. */
111 RTSEMEVENT hEvtGlobal;
112 /** Notification event bitmap. */
113 volatile uint64_t bmEvt;
114 /** Number of threads created - one for each process. */
115 uint32_t cThrds;
116 /** Pointer to the array of observer thread states. */
117 PRTFUZZOBSTHRD paObsThrds;
118} RTFUZZOBSINT;
119
120
121/*********************************************************************************************************************************
122* Global variables *
123*********************************************************************************************************************************/
124
125
126
127/*********************************************************************************************************************************
128* Internal Functions *
129*********************************************************************************************************************************/
130
131
132/**
133 * Fuzzing observer worker loop.
134 *
135 * @returns IPRT status code.
136 * @param hThrd The thread handle.
137 * @param pvUser Opaque user data.
138 */
139static DECLCALLBACK(int) rtFuzzObsWorkerLoop(RTTHREAD hThrd, void *pvUser)
140{
141 PRTFUZZOBSTHRD pObsThrd = (PRTFUZZOBSTHRD)pvUser;
142 PRTFUZZOBSINT pThis = pObsThrd->pFuzzObs;
143 char **papszArgs = NULL;
144 RTHANDLE NilHandle;
145 NilHandle.enmType = RTHANDLETYPE_PIPE;
146 NilHandle.u.hPipe = NIL_RTPIPE;
147
148 if (!(pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE))
149 {
150 papszArgs = (char **)RTMemAllocZ((pThis->cArgs + 1) * sizeof(char *));
151 if (RT_LIKELY(papszArgs))
152 {
153 for (uint32_t i = 0; i < pThis->cArgs; i++)
154 papszArgs[i] = pThis->papszArgs[i];
155 }
156 }
157 else
158 papszArgs = pThis->papszArgs;
159
160 while (!pObsThrd->fShutdown)
161 {
162 /* Wait for work. */
163 int rc = RTThreadUserWait(hThrd, RT_INDEFINITE_WAIT);
164 AssertRC(rc);
165
166 if (pObsThrd->fShutdown)
167 break;
168
169 bool f = ASMAtomicXchgBool(&pObsThrd->fNewInput, false);
170 if (!f)
171 continue;
172
173 AssertPtr(pObsThrd->hFuzzInput);
174
175 /* Create the stdout/stderr pipe. */
176 RTPIPE hPipeStdOutErrR;
177 RTPIPE hPipeStdOutErrW;
178 rc = RTPipeCreate(&hPipeStdOutErrR, &hPipeStdOutErrW, RTPIPE_C_INHERIT_WRITE);
179 if (RT_SUCCESS(rc))
180 {
181 RTHANDLE HandleStdOutErr;
182 HandleStdOutErr.enmType = RTHANDLETYPE_PIPE;
183 HandleStdOutErr.u.hPipe = hPipeStdOutErrW;
184
185 if (pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)
186 {
187 char szInput[RTPATH_MAX];
188 char szDigest[RTMD5_STRING_LEN + 1];
189 char szFilename[sizeof(szDigest) + 32];
190
191 rc = RTFuzzInputQueryDigestString(pObsThrd->hFuzzInput, &szDigest[0], sizeof(szDigest));
192 AssertRC(rc);
193
194 ssize_t cbBuf = RTStrPrintf2(&szFilename[0], sizeof(szFilename), "%u-%s", pObsThrd->idObs, &szDigest[0]);
195 Assert(cbBuf > 0); RT_NOREF(cbBuf);
196
197 RT_ZERO(szInput);
198 rc = RTPathJoin(szInput, sizeof(szInput), pThis->pszTmpDir, &szFilename[0]);
199 AssertRC(rc);
200
201 rc = RTFuzzInputWriteToFile(pObsThrd->hFuzzInput, &szInput[0]);
202 if (RT_SUCCESS(rc))
203 {
204 papszArgs[pThis->cArgs - 1] = &szInput[0];
205
206 RTPROCESS hProc = NIL_RTPROCESS;
207 rc = RTProcCreateEx(pThis->pszBinary, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &NilHandle,
208 NULL, NULL, NULL, NULL, &hProc);
209 if (RT_SUCCESS(rc))
210 {
211 RTPipeClose(hPipeStdOutErrW);
212 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
213 rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus);
214 if (RT_SUCCESS(rc))
215 {
216 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL)
217 {
218 pObsThrd->fKeepInput = true;
219 RTPrintf("Abnormal exit detected!\n");
220 }
221 else
222 {
223 /*
224 * Fuzzed inputs are only added if the client signalled a success in parsing the input.
225 * Inputs which lead to errors are not added because it is assumed that the target
226 * successfully verified the input data.
227 */
228 //if (ProcStatus.iStatus == RTEXITCODE_SUCCESS)
229 // pObsThrd->fKeepInput = true;
230 }
231 }
232 else
233 AssertFailed();
234 }
235 else
236 AssertFailed();
237
238 rc = RTFileDelete(&szInput[0]);
239 AssertRC(rc);
240 }
241 else
242 AssertFailed();
243 }
244 else
245 {
246 RTPIPE hPipeR;
247 RTPIPE hPipeW;
248 rc = RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ);
249 if (RT_SUCCESS(rc))
250 {
251 RTPROCESS hProc = NIL_RTPROCESS;
252 RTHANDLE Handle;
253 Handle.enmType = RTHANDLETYPE_PIPE;
254 Handle.u.hPipe = hPipeR;
255 rc = RTProcCreateEx(pThis->pszBinary, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &Handle,
256 &HandleStdOutErr, &HandleStdOutErr, NULL, NULL, &hProc);
257 if (RT_SUCCESS(rc))
258 {
259 /* Pump the input data. */
260 RTPipeClose(hPipeStdOutErrW);
261
262 uint8_t *pbInput;
263 size_t cbInput;
264 rc = RTFuzzInputQueryData(pObsThrd->hFuzzInput, (void **)&pbInput, &cbInput);
265 if (RT_SUCCESS(rc))
266 {
267 rc = RTPipeWriteBlocking(hPipeW, pbInput, cbInput, NULL);
268 RTPipeClose(hPipeW);
269
270 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
271 rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus);
272 if (RT_SUCCESS(rc))
273 {
274 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL)
275 {
276 pObsThrd->fKeepInput = true;
277 RTPrintf("Abnormal exit detected!\n");
278 }
279 else
280 {
281 /*
282 * Fuzzed inputs are only added if the client signalled a success in parsing the input.
283 * Inputs which lead to errors are not added because it is assumed that the target
284 * successfully verified the input data.
285 */
286 if (ProcStatus.iStatus == RTEXITCODE_SUCCESS)
287 pObsThrd->fKeepInput = true;
288 }
289 }
290 }
291 }
292
293 RTPipeClose(hPipeW);
294 }
295 }
296
297 RTPipeClose(hPipeStdOutErrR);
298 }
299 else
300 AssertFailed();
301
302 ASMAtomicBitSet(&pThis->bmEvt, pObsThrd->idObs);
303 RTSemEventSignal(pThis->hEvtGlobal);
304 }
305
306 return VINF_SUCCESS;
307}
308
309
310/**
311 * Fuzzing observer master worker loop.
312 *
313 * @returns IPRT status code.
314 * @param hThrd The thread handle.
315 * @param pvUser Opaque user data.
316 */
317static DECLCALLBACK(int) rtFuzzObsMasterLoop(RTTHREAD hThrd, void *pvUser)
318{
319 RT_NOREF(hThrd);
320 int rc = VINF_SUCCESS;
321 PRTFUZZOBSINT pThis = (PRTFUZZOBSINT)pvUser;
322
323 RTThreadUserSignal(hThrd);
324
325 while ( !pThis->fShutdown
326 && RT_SUCCESS(rc))
327 {
328 uint64_t bmEvt = ASMAtomicXchgU64(&pThis->bmEvt, 0);
329 uint32_t idxObs = 0;
330 while (bmEvt != 0)
331 {
332 if (bmEvt & 0x1)
333 {
334 /* Create a new input for this observer and kick it. */
335 PRTFUZZOBSTHRD pObsThrd = &pThis->paObsThrds[idxObs];
336
337 /* Release the old input. */
338 if (pObsThrd->hFuzzInput)
339 {
340 if (pObsThrd->fKeepInput)
341 {
342 int rc2 = RTFuzzInputAddToCtxCorpus(pObsThrd->hFuzzInput);
343 Assert(RT_SUCCESS(rc2) || rc2 == VERR_ALREADY_EXISTS); RT_NOREF(rc2);
344 pObsThrd->fKeepInput= false;
345 }
346 RTFuzzInputRelease(pObsThrd->hFuzzInput);
347 }
348
349 rc = RTFuzzCtxInputGenerate(pThis->hFuzzCtx, &pObsThrd->hFuzzInput);
350 if (RT_SUCCESS(rc))
351 {
352 ASMAtomicWriteBool(&pObsThrd->fNewInput, true);
353 RTThreadUserSignal(pObsThrd->hThrd);
354 }
355 }
356
357 idxObs++;
358 bmEvt >>= 1;
359 }
360
361 rc = RTSemEventWait(pThis->hEvtGlobal, RT_INDEFINITE_WAIT);
362 }
363
364 return VINF_SUCCESS;
365}
366
367
368/**
369 * Initializes the given worker thread structure.
370 *
371 * @returns IPRT status code.
372 * @param pThis The internal fuzzing observer state.
373 * @param iObs Observer ID.
374 * @param pObsThrd The observer thread structure.
375 */
376static int rtFuzzObsWorkerThreadInit(PRTFUZZOBSINT pThis, uint32_t idObs, PRTFUZZOBSTHRD pObsThrd)
377{
378 pObsThrd->pFuzzObs = pThis;
379 pObsThrd->hFuzzInput = NULL;
380 pObsThrd->idObs = idObs;
381 pObsThrd->fShutdown = false;
382
383 ASMAtomicBitSet(&pThis->bmEvt, idObs);
384 return RTThreadCreate(&pObsThrd->hThrd, rtFuzzObsWorkerLoop, pObsThrd, 0, RTTHREADTYPE_IO,
385 RTTHREADFLAGS_WAITABLE, "Fuzz-Worker");
386}
387
388
389/**
390 * Creates the given amount of worker threads and puts them into waiting state.
391 *
392 * @returns IPRT status code.
393 * @param pThis The internal fuzzing observer state.
394 * @param cThrds Number of worker threads to create.
395 */
396static int rtFuzzObsWorkersCreate(PRTFUZZOBSINT pThis, uint32_t cThrds)
397{
398 int rc = VINF_SUCCESS;
399 PRTFUZZOBSTHRD paObsThrds = (PRTFUZZOBSTHRD)RTMemAllocZ(cThrds * sizeof(RTFUZZOBSTHRD));
400 if (RT_LIKELY(paObsThrds))
401 {
402 for (unsigned i = 0; i < cThrds && RT_SUCCESS(rc); i++)
403 {
404 rc = rtFuzzObsWorkerThreadInit(pThis, i, &paObsThrds[i]);
405 if (RT_FAILURE(rc))
406 {
407 /* Rollback. */
408
409 }
410 }
411
412 if (RT_SUCCESS(rc))
413 pThis->paObsThrds = paObsThrds;
414 else
415 RTMemFree(paObsThrds);
416 }
417
418 return rc;
419}
420
421
422/**
423 * Creates the global worker thread managing the input creation and other worker threads.
424 *
425 * @returns IPRT status code.
426 * @param pThis The internal fuzzing observer state.
427 */
428static int rtFuzzObsMasterCreate(PRTFUZZOBSINT pThis)
429{
430 pThis->fShutdown = false;
431
432 int rc = RTSemEventCreate(&pThis->hEvtGlobal);
433 if (RT_SUCCESS(rc))
434 {
435 rc = RTThreadCreate(&pThis->hThrdGlobal, rtFuzzObsMasterLoop, pThis, 0, RTTHREADTYPE_IO,
436 RTTHREADFLAGS_WAITABLE, "Fuzz-Master");
437 if (RT_SUCCESS(rc))
438 {
439 RTThreadUserWait(pThis->hThrdGlobal, RT_INDEFINITE_WAIT);
440 }
441 else
442 {
443 RTSemEventDestroy(pThis->hEvtGlobal);
444 pThis->hEvtGlobal = NIL_RTSEMEVENT;
445 }
446 }
447
448 return rc;
449}
450
451
452RTDECL(int) RTFuzzObsCreate(PRTFUZZOBS phFuzzObs)
453{
454 AssertPtrReturn(phFuzzObs, VERR_INVALID_POINTER);
455
456 int rc = VINF_SUCCESS;
457 PRTFUZZOBSINT pThis = (PRTFUZZOBSINT)RTMemAllocZ(sizeof(*pThis));
458 if (RT_LIKELY(pThis))
459 {
460 pThis->pszBinary = NULL;
461 pThis->papszArgs = NULL;
462 pThis->fFlags = 0;
463 pThis->hThrdGlobal = NIL_RTTHREAD;
464 pThis->hEvtGlobal = NIL_RTSEMEVENT;
465 pThis->bmEvt = 0;
466 pThis->cThrds = 0;
467 pThis->paObsThrds = NULL;
468 rc = RTFuzzCtxCreate(&pThis->hFuzzCtx);
469 if (RT_SUCCESS(rc))
470 {
471 *phFuzzObs = pThis;
472 return VINF_SUCCESS;
473 }
474
475 RTMemFree(pThis);
476 }
477 else
478 rc = VERR_NO_MEMORY;
479
480 return rc;
481}
482
483
484RTDECL(int) RTFuzzObsDestroy(RTFUZZOBS hFuzzObs)
485{
486 PRTFUZZOBSINT pThis = hFuzzObs;
487 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
488
489 /* Wait for the master thread to terminate. */
490 if (pThis->hThrdGlobal != NIL_RTTHREAD)
491 {
492 ASMAtomicXchgBool(&pThis->fShutdown, true);
493 RTThreadWait(pThis->hThrdGlobal, RT_INDEFINITE_WAIT, NULL);
494 }
495
496 /* Clean up the workers. */
497 if (pThis->paObsThrds)
498 {
499 for (unsigned i = 0; i < pThis->cThrds; i++)
500 {
501 PRTFUZZOBSTHRD pThrd = &pThis->paObsThrds[i];
502 ASMAtomicXchgBool(&pThrd->fShutdown, true);
503 RTThreadWait(pThrd->hThrd, RT_INDEFINITE_WAIT, NULL);
504 if (pThrd->hFuzzInput)
505 RTFuzzInputRelease(pThrd->hFuzzInput);
506 }
507 RTMemFree(pThis->paObsThrds);
508 pThis->paObsThrds = NULL;
509 }
510
511 /* Clean up all acquired resources. */
512 for (unsigned i = 0; i < pThis->cArgs; i++)
513 RTStrFree(pThis->papszArgs[i]);
514
515 RTMemFree(pThis->papszArgs);
516
517 if (pThis->hEvtGlobal != NIL_RTSEMEVENT)
518 RTSemEventDestroy(pThis->hEvtGlobal);
519
520 if (pThis->pszBinary)
521 RTStrFree(pThis->pszBinary);
522 RTFuzzCtxRelease(pThis->hFuzzCtx);
523 RTMemFree(pThis);
524 return VINF_SUCCESS;
525}
526
527
528RTDECL(int) RTFuzzObsQueryCtx(RTFUZZOBS hFuzzObs, PRTFUZZCTX phFuzzCtx)
529{
530 PRTFUZZOBSINT pThis = hFuzzObs;
531 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
532 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
533
534 RTFuzzCtxRetain(pThis->hFuzzCtx);
535 *phFuzzCtx = pThis->hFuzzCtx;
536 return VINF_SUCCESS;
537}
538
539
540RTDECL(int) RTFuzzObsSetTmpDirectory(RTFUZZOBS hFuzzObs, const char *pszTmp)
541{
542 PRTFUZZOBSINT pThis = hFuzzObs;
543 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
544 AssertPtrReturn(pszTmp, VERR_INVALID_POINTER);
545
546 int rc = VINF_SUCCESS;
547 pThis->pszTmpDir = RTStrDup(pszTmp);
548 if (!pThis->pszTmpDir)
549 rc = VERR_NO_STR_MEMORY;
550 return rc;
551}
552
553
554RTDECL(int) RTFuzzObsSetTestBinary(RTFUZZOBS hFuzzObs, const char *pszBinary, uint32_t fFlags)
555{
556 PRTFUZZOBSINT pThis = hFuzzObs;
557 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
558 AssertPtrReturn(pszBinary, VERR_INVALID_POINTER);
559
560 int rc = VINF_SUCCESS;
561 pThis->fFlags = fFlags;
562 pThis->pszBinary = RTStrDup(pszBinary);
563 if (RT_UNLIKELY(!pThis->pszBinary))
564 rc = VERR_NO_STR_MEMORY;
565 return rc;
566}
567
568
569RTDECL(int) RTFuzzObsSetTestBinaryArgs(RTFUZZOBS hFuzzObs, const char * const *papszArgs, unsigned cArgs)
570{
571 PRTFUZZOBSINT pThis = hFuzzObs;
572 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
573
574 int rc = VINF_SUCCESS;
575 char **papszArgsOld = pThis->papszArgs;
576 if (papszArgs)
577 {
578 pThis->papszArgs = (char **)RTMemAllocZ(sizeof(char **) * (cArgs + 1));
579 if (RT_LIKELY(pThis->papszArgs))
580 {
581 char **ppszOwn = pThis->papszArgs;
582 const char * const *ppsz = papszArgs;
583 while ( *ppsz != NULL
584 && RT_SUCCESS(rc))
585 {
586 *ppszOwn = RTStrDup(*ppsz);
587 if (RT_UNLIKELY(!*ppszOwn))
588 {
589 while (ppszOwn > pThis->papszArgs)
590 {
591 ppszOwn--;
592 RTStrFree(*ppszOwn);
593 }
594 break;
595 }
596
597 ppszOwn++;
598 ppsz++;
599 }
600
601 if (RT_FAILURE(rc))
602 RTMemFree(pThis->papszArgs);
603 }
604 else
605 rc = VERR_NO_MEMORY;
606
607 if (RT_FAILURE(rc))
608 pThis->papszArgs = papszArgsOld;
609 else
610 pThis->cArgs = cArgs;
611 }
612 else
613 {
614 pThis->papszArgs = NULL;
615 pThis->cArgs = 0;
616 if (papszArgsOld)
617 {
618 char **ppsz = papszArgsOld;
619 while (*ppsz != NULL)
620 {
621 RTStrFree(*ppsz);
622 ppsz++;
623 }
624 RTMemFree(papszArgsOld);
625 }
626 }
627
628 return rc;
629}
630
631
632RTDECL(int) RTFuzzObsExecStart(RTFUZZOBS hFuzzObs, uint32_t cProcs)
633{
634 PRTFUZZOBSINT pThis = hFuzzObs;
635 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
636 AssertReturn(cProcs <= sizeof(uint64_t) * 8, VERR_INVALID_PARAMETER);
637 AssertReturn( (pThis->fFlags & RTFUZZ_OBS_BINARY_F_INPUT_FILE)
638 || pThis->pszTmpDir != NULL,
639 VERR_INVALID_STATE);
640
641 int rc = VINF_SUCCESS;
642 if (!cProcs)
643 cProcs = RT_MIN(RTMpGetPresentCoreCount(), sizeof(uint64_t) * 8);
644
645 /* Spin up the worker threads first. */
646 rc = rtFuzzObsWorkersCreate(pThis, cProcs);
647 if (RT_SUCCESS(rc))
648 {
649 /* Spin up the global thread. */
650 rc = rtFuzzObsMasterCreate(pThis);
651 }
652
653 return rc;
654}
655
656
657RTDECL(int) RTFuzzObsExecStop(RTFUZZOBS hFuzzObs)
658{
659 RT_NOREF(hFuzzObs);
660 return VERR_NOT_IMPLEMENTED;
661}
662
Note: See TracBrowser for help on using the repository browser.

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