VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/fuzz/fuzz-target-recorder.cpp@ 77693

Last change on this file since 77693 was 77693, checked in by vboxsync, 6 years ago

Runtime/fuzz: Some more statistics, add possibility to configure the environment of the target process through the job config, add possibility to read SanitizerCoverage generated reports to scan for changes in executed paths for inputs to evaluate which mutations are interesting for further use

  • 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-target-recorder.cpp 77693 2019-03-13 21:24:29Z vboxsync $ */
2/** @file
3 * IPRT - Fuzzing framework API, target state recorder.
4 */
5
6/*
7 * Copyright (C) 2019 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/fuzz.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/avl.h>
37#include <iprt/crc.h>
38#include <iprt/ctype.h>
39#include <iprt/err.h>
40#include <iprt/file.h>
41#include <iprt/list.h>
42#include <iprt/mem.h>
43#include <iprt/pipe.h>
44#include <iprt/semaphore.h>
45#include <iprt/string.h>
46
47
48
49/*********************************************************************************************************************************
50* Structures and Typedefs *
51*********************************************************************************************************************************/
52/** Pointer to the internal fuzzed target recorder state. */
53typedef struct RTFUZZTGTRECINT *PRTFUZZTGTRECINT;
54
55
56/**
57 * Stdout/Stderr buffer.
58 */
59typedef struct RTFUZZTGTSTDOUTERRBUF
60{
61 /** Current amount buffered. */
62 size_t cbBuf;
63 /** Maxmium amount to buffer. */
64 size_t cbBufMax;
65 /** Base pointer to the data buffer. */
66 uint8_t *pbBase;
67} RTFUZZTGTSTDOUTERRBUF;
68/** Pointer to a stdout/stderr buffer. */
69typedef RTFUZZTGTSTDOUTERRBUF *PRTFUZZTGTSTDOUTERRBUF;
70
71
72/**
73 * Internal fuzzed target state.
74 */
75typedef struct RTFUZZTGTSTATEINT
76{
77 /** Node for the list of states. */
78 RTLISTNODE NdStates;
79 /** Checksum for the state. */
80 uint64_t uChkSum;
81 /** Magic identifying the structure. */
82 uint32_t u32Magic;
83 /** Reference counter. */
84 volatile uint32_t cRefs;
85 /** The owning recorder instance. */
86 PRTFUZZTGTRECINT pTgtRec;
87 /** Flag whether the state is finalized. */
88 bool fFinalized;
89 /** Flag whether the state is contained in the recorded set. */
90 bool fInRecSet;
91 /** The stdout data buffer. */
92 RTFUZZTGTSTDOUTERRBUF StdOutBuf;
93 /** The stderr data buffer. */
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;
101} RTFUZZTGTSTATEINT;
102/** Pointer to an internal fuzzed target state. */
103typedef RTFUZZTGTSTATEINT *PRTFUZZTGTSTATEINT;
104
105
106/**
107 * Recorder states node in the AVL tree.
108 */
109typedef struct RTFUZZTGTRECNODE
110{
111 /** The AVL tree core (keyed by checksum). */
112 AVLU64NODECORE Core;
113 /** The list anchor for the individual states. */
114 RTLISTANCHOR LstStates;
115} RTFUZZTGTRECNODE;
116/** Pointer to a recorder states node. */
117typedef RTFUZZTGTRECNODE *PRTFUZZTGTRECNODE;
118
119
120/**
121 * Edge information node.
122 */
123typedef 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. */
131typedef RTFUZZTGTEDGE *PRTFUZZTGTEDGE;
132
133
134/**
135 * Internal fuzzed target recorder state.
136 */
137typedef struct RTFUZZTGTRECINT
138{
139 /** Magic value for identification. */
140 uint32_t u32Magic;
141 /** Reference counter. */
142 volatile uint32_t cRefs;
143 /** Semaphore protecting the states tree. */
144 RTSEMRW hSemRwStates;
145 /** The AVL tree for indexing the recorded state (keyed by stdout/stderr buffer size). */
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;
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)
162
163
164/*********************************************************************************************************************************
165* Internal Functions *
166*********************************************************************************************************************************/
167
168/**
169 * Initializes the given stdout/stderr buffer.
170 *
171 * @returns nothing.
172 * @param pBuf The buffer to initialize.
173 */
174static void rtFuzzTgtStdOutErrBufInit(PRTFUZZTGTSTDOUTERRBUF pBuf)
175{
176 pBuf->cbBuf = 0;
177 pBuf->cbBufMax = 0;
178 pBuf->pbBase = NULL;
179}
180
181
182/**
183 * Frees all allocated resources in the given stdout/stderr buffer.
184 *
185 * @returns nothing.
186 * @param pBuf The buffer to free.
187 */
188static void rtFuzzTgtStdOutErrBufFree(PRTFUZZTGTSTDOUTERRBUF pBuf)
189{
190 if (pBuf->pbBase)
191 RTMemFree(pBuf->pbBase);
192}
193
194
195/**
196 * Fills the given stdout/stderr buffer from the given pipe.
197 *
198 * @returns IPRT status code.
199 * @param pBuf The buffer to fill.
200 * @param hPipeRead The pipe to read from.
201 */
202static int rtFuzzTgtStdOutErrBufFillFromPipe(PRTFUZZTGTSTDOUTERRBUF pBuf, RTPIPE hPipeRead)
203{
204 int rc = VINF_SUCCESS;
205
206 size_t cbRead = 0;
207 size_t cbThisRead = 0;
208 do
209 {
210 cbThisRead = pBuf->cbBufMax - pBuf->cbBuf;
211 if (!cbThisRead)
212 {
213 /* Try to increase the buffer. */
214 uint8_t *pbNew = (uint8_t *)RTMemRealloc(pBuf->pbBase, pBuf->cbBufMax + _4K);
215 if (RT_LIKELY(pbNew))
216 {
217 pBuf->cbBufMax += _4K;
218 pBuf->pbBase = pbNew;
219 }
220 cbThisRead = pBuf->cbBufMax - pBuf->cbBuf;
221 }
222
223 if (cbThisRead)
224 {
225 rc = RTPipeRead(hPipeRead, pBuf->pbBase + pBuf->cbBuf, cbThisRead, &cbRead);
226 if (RT_SUCCESS(rc))
227 pBuf->cbBuf += cbRead;
228 }
229 else
230 rc = VERR_NO_MEMORY;
231 } while ( RT_SUCCESS(rc)
232 && cbRead == cbThisRead);
233
234 return rc;
235}
236
237
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 */
245static 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/**
317 * Destorys the given fuzzer target recorder freeing all allocated resources.
318 *
319 * @returns nothing.
320 * @param pThis The fuzzer target recorder instance.
321 */
322static void rtFuzzTgtRecDestroy(PRTFUZZTGTRECINT pThis)
323{
324 RT_NOREF(pThis);
325}
326
327
328/**
329 * Destroys the given fuzzer target state freeing all allocated resources.
330 *
331 * @returns nothing.
332 * @param pThis The fuzzed target state instance.
333 */
334static void rtFuzzTgtStateDestroy(PRTFUZZTGTSTATEINT pThis)
335{
336 pThis->u32Magic = ~(uint32_t)0; /** @todo Dead magic */
337 rtFuzzTgtStdOutErrBufFree(&pThis->StdOutBuf);
338 rtFuzzTgtStdOutErrBufFree(&pThis->StdErrBuf);
339 RTMemFree(pThis);
340}
341
342
343RTDECL(int) RTFuzzTgtRecorderCreate(PRTFUZZTGTREC phFuzzTgtRec)
344{
345 int rc;
346 PRTFUZZTGTRECINT pThis = (PRTFUZZTGTRECINT)RTMemAllocZ(sizeof(*pThis));
347 if (RT_LIKELY(pThis))
348 {
349 pThis->u32Magic = 0; /** @todo */
350 pThis->cRefs = 1;
351 pThis->TreeStates = NULL;
352 pThis->TreeEdges = NULL;
353 pThis->cbCovOff = 0;
354
355 rc = RTSemRWCreate(&pThis->hSemRwStates);
356 if (RT_SUCCESS(rc))
357 {
358 rc = RTSemRWCreate(&pThis->hSemRwEdges);
359 if (RT_SUCCESS(rc))
360 {
361 *phFuzzTgtRec = pThis;
362 return VINF_SUCCESS;
363 }
364
365 RTSemRWDestroy(pThis->hSemRwStates);
366 }
367
368 RTMemFree(pThis);
369 }
370 else
371 rc = VERR_NO_MEMORY;
372
373 return rc;
374}
375
376
377RTDECL(uint32_t) RTFuzzTgtRecorderRetain(RTFUZZTGTREC hFuzzTgtRec)
378{
379 PRTFUZZTGTRECINT pThis = hFuzzTgtRec;
380
381 AssertPtrReturn(pThis, UINT32_MAX);
382
383 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
384 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
385 return cRefs;
386}
387
388
389RTDECL(uint32_t) RTFuzzTgtRecorderRelease(RTFUZZTGTREC hFuzzTgtRec)
390{
391 PRTFUZZTGTRECINT pThis = hFuzzTgtRec;
392 if (pThis == NIL_RTFUZZTGTREC)
393 return 0;
394 AssertPtrReturn(pThis, UINT32_MAX);
395
396 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
397 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
398 if (cRefs == 0)
399 rtFuzzTgtRecDestroy(pThis);
400 return cRefs;
401}
402
403
404RTDECL(int) RTFuzzTgtRecorderCreateNewState(RTFUZZTGTREC hFuzzTgtRec, PRTFUZZTGTSTATE phFuzzTgtState)
405{
406 PRTFUZZTGTRECINT pThis = hFuzzTgtRec;
407 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
408 AssertPtrReturn(phFuzzTgtState, VERR_INVALID_POINTER);
409
410 int rc = VINF_SUCCESS;
411 PRTFUZZTGTSTATEINT pState = (PRTFUZZTGTSTATEINT)RTMemAllocZ(sizeof(*pState));
412 if (RT_LIKELY(pState))
413 {
414 pState->u32Magic = 0; /** @todo */
415 pState->cRefs = 1;
416 pState->pTgtRec = pThis;
417 pState->fFinalized = false;
418 rtFuzzTgtStdOutErrBufInit(&pState->StdOutBuf);
419 rtFuzzTgtStdOutErrBufInit(&pState->StdErrBuf);
420 *phFuzzTgtState = pState;
421 }
422 else
423 rc = VERR_NO_MEMORY;
424
425 return rc;
426}
427
428
429RTDECL(uint32_t) RTFuzzTgtStateRetain(RTFUZZTGTSTATE hFuzzTgtState)
430{
431 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
432
433 AssertPtrReturn(pThis, UINT32_MAX);
434
435 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
436 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
437 return cRefs;
438}
439
440
441RTDECL(uint32_t) RTFuzzTgtStateRelease(RTFUZZTGTSTATE hFuzzTgtState)
442{
443 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
444 if (pThis == NIL_RTFUZZTGTSTATE)
445 return 0;
446 AssertPtrReturn(pThis, UINT32_MAX);
447
448 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
449 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
450 if (cRefs == 0 && !pThis->fInRecSet)
451 rtFuzzTgtStateDestroy(pThis);
452 return cRefs;
453}
454
455
456RTDECL(int) RTFuzzTgtStateReset(RTFUZZTGTSTATE hFuzzTgtState)
457{
458 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
459 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
460
461 /* Clear the buffers. */
462 pThis->StdOutBuf.cbBuf = 0;
463 pThis->StdErrBuf.cbBuf = 0;
464 if (pThis->pvCovReport)
465 RTMemFree(pThis->pvCovReport);
466 pThis->pvCovReport = NULL;
467 pThis->fFinalized = false;
468 return VINF_SUCCESS;
469}
470
471
472RTDECL(int) RTFuzzTgtStateFinalize(RTFUZZTGTSTATE hFuzzTgtState)
473{
474 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
475 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
476
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);
487 pThis->fFinalized = true;
488 return VINF_SUCCESS;
489}
490
491
492RTDECL(int) RTFuzzTgtStateAddToRecorder(RTFUZZTGTSTATE hFuzzTgtState)
493{
494 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
495 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
496
497 if (!pThis->fFinalized)
498 {
499 int rc = RTFuzzTgtStateFinalize(pThis);
500 if (RT_FAILURE(rc))
501 return rc;
502 }
503
504 PRTFUZZTGTRECINT pTgtRec = pThis->pTgtRec;
505
506 /* Try to find a node matching the stdout and sterr sizes first. */
507 int rc = RTSemRWRequestRead(pTgtRec->hSemRwStates, RT_INDEFINITE_WAIT); AssertRC(rc);
508 PRTFUZZTGTRECNODE pNode = (PRTFUZZTGTRECNODE)RTAvlU64Get(&pTgtRec->TreeStates, pThis->uChkSum);
509 if (pNode)
510 {
511 /* Traverse the states and check if any matches the stdout and stderr buffers exactly. */
512 PRTFUZZTGTSTATEINT pIt;
513 bool fMatchFound = false;
514 RTListForEach(&pNode->LstStates, pIt, RTFUZZTGTSTATEINT, NdStates)
515 {
516 Assert( pThis->StdOutBuf.cbBuf == pIt->StdOutBuf.cbBuf
517 && pThis->StdErrBuf.cbBuf == pIt->StdErrBuf.cbBuf);
518 if ( ( !pThis->StdOutBuf.cbBuf
519 || !memcmp(pThis->StdOutBuf.pbBase, pIt->StdOutBuf.pbBase, pThis->StdOutBuf.cbBuf))
520 && ( !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))))
525 {
526 fMatchFound = true;
527 break;
528 }
529 }
530
531 rc = RTSemRWReleaseRead(pTgtRec->hSemRwStates); AssertRC(rc);
532 if (!fMatchFound)
533 {
534 rc = RTSemRWRequestWrite(pTgtRec->hSemRwStates, RT_INDEFINITE_WAIT); AssertRC(rc);
535 RTListAppend(&pNode->LstStates, &pThis->NdStates);
536 rc = RTSemRWReleaseWrite(pTgtRec->hSemRwStates); AssertRC(rc);
537 pThis->fInRecSet = true;
538 }
539 else
540 rc = VERR_ALREADY_EXISTS;
541 }
542 else
543 {
544 rc = RTSemRWReleaseRead(pTgtRec->hSemRwStates); AssertRC(rc);
545
546 /* No node found, create new one and insert in to the tree right away. */
547 pNode = (PRTFUZZTGTRECNODE)RTMemAllocZ(sizeof(*pNode));
548 if (RT_LIKELY(pNode))
549 {
550 pNode->Core.Key = pThis->uChkSum;
551 RTListInit(&pNode->LstStates);
552 RTListAppend(&pNode->LstStates, &pThis->NdStates);
553 rc = RTSemRWRequestWrite(pTgtRec->hSemRwStates, RT_INDEFINITE_WAIT); AssertRC(rc);
554 bool fIns = RTAvlU64Insert(&pTgtRec->TreeStates, &pNode->Core);
555 if (!fIns)
556 {
557 /* Someone raced us, get the new node and append there. */
558 RTMemFree(pNode);
559 pNode = (PRTFUZZTGTRECNODE)RTAvlU64Get(&pTgtRec->TreeStates, pThis->uChkSum);
560 AssertPtr(pNode);
561 RTListAppend(&pNode->LstStates, &pThis->NdStates);
562 }
563 rc = RTSemRWReleaseWrite(pTgtRec->hSemRwStates); AssertRC(rc);
564 pThis->fInRecSet = true;
565 }
566 else
567 rc = VERR_NO_MEMORY;
568 }
569
570 if ( RT_SUCCESS(rc)
571 && pThis->fInRecSet)
572 rc = rtFuzzTgtRecScanStateForNewEdges(pTgtRec, pThis);
573
574 return rc;
575}
576
577
578RTDECL(int) RTFuzzTgtStateAppendStdoutFromBuf(RTFUZZTGTSTATE hFuzzTgtState, const void *pvStdOut, size_t cbStdOut)
579{
580 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
581 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
582 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
583
584 RT_NOREF(pvStdOut, cbStdOut);
585 return VERR_NOT_IMPLEMENTED;
586}
587
588
589RTDECL(int) RTFuzzTgtStateAppendStderrFromBuf(RTFUZZTGTSTATE hFuzzTgtState, const void *pvStdErr, size_t cbStdErr)
590{
591 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
592 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
593 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
594
595 RT_NOREF(pvStdErr, cbStdErr);
596 return VERR_NOT_IMPLEMENTED;
597}
598
599
600RTDECL(int) RTFuzzTgtStateAppendStdoutFromPipe(RTFUZZTGTSTATE hFuzzTgtState, RTPIPE hPipe)
601{
602 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
603 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
604 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
605
606 return rtFuzzTgtStdOutErrBufFillFromPipe(&pThis->StdOutBuf, hPipe);
607}
608
609
610RTDECL(int) RTFuzzTgtStateAppendStderrFromPipe(RTFUZZTGTSTATE hFuzzTgtState, RTPIPE hPipe)
611{
612 PRTFUZZTGTSTATEINT pThis = hFuzzTgtState;
613 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
614 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
615
616 return rtFuzzTgtStdOutErrBufFillFromPipe(&pThis->StdErrBuf, hPipe);
617}
618
619
620RTDECL(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
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