VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp@ 77564

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

Runtime/fuzz: Add libFuzzer compatible wrapper to be able to evaluate our fuzzer against others

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 58.2 KB
Line 
1/* $Id: fuzz.cpp 77564 2019-03-05 10:30:33Z vboxsync $ */
2/** @file
3 * IPRT - Fuzzing framework API, core.
4 */
5
6/*
7 * Copyright (C) 2018-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/ctype.h>
38#include <iprt/dir.h>
39#include <iprt/err.h>
40#include <iprt/file.h>
41#include <iprt/list.h>
42#include <iprt/md5.h>
43#include <iprt/mem.h>
44#include <iprt/path.h>
45#include <iprt/rand.h>
46#include <iprt/semaphore.h>
47#include <iprt/string.h>
48#include <iprt/time.h>
49#include <iprt/vfs.h>
50
51
52#define RTFUZZCTX_MAGIC UINT32_C(0xdeadc0de) /** @todo */
53
54
55/*********************************************************************************************************************************
56* Structures and Typedefs *
57*********************************************************************************************************************************/
58/** Pointer to the internal fuzzer state. */
59typedef struct RTFUZZCTXINT *PRTFUZZCTXINT;
60/** Pointer to a fuzzed mutation. */
61typedef struct RTFUZZMUTATION *PRTFUZZMUTATION;
62/** Pointer to a fuzzed mutation pointer. */
63typedef PRTFUZZMUTATION *PPRTFUZZMUTATION;
64/** Pointer to a const mutation. */
65typedef const struct RTFUZZMUTATION *PCRTFUZZMUTATION;
66
67
68/**
69 * Mutator preparation callback.
70 *
71 * @returns IPRT status code.
72 * @param pThis The fuzzer context instance.
73 * @param offStart Where the mutation should start.
74 * @param pMutationParent The parent mutation to start working from.
75 * @param ppMutation Where to store the created mutation on success.
76 */
77typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATORPREP(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
78 PPRTFUZZMUTATION ppMutation);
79/** Pointer to a mutator preparation callback. */
80typedef FNRTFUZZCTXMUTATORPREP *PFNRTFUZZCTXMUTATORPREP;
81
82
83/**
84 * Mutator execution callback.
85 *
86 * @returns IPRT status code.
87 * @param pThis The fuzzer context instance.
88 * @param pMutation The mutation to work on.
89 * @param pvMutation Mutation dependent data.
90 * @param pbBuf The buffer to work on.
91 * @param cbBuf Size of the remaining buffer.
92 */
93typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXEC(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
94 uint8_t *pbBuf, size_t cbBuf);
95/** Pointer to a mutator execution callback. */
96typedef FNRTFUZZCTXMUTATOREXEC *PFNRTFUZZCTXMUTATOREXEC;
97
98
99/**
100 * Mutator export callback.
101 *
102 * @returns IPRT status code.
103 * @param pThis The fuzzer context instance.
104 * @param pMutation The mutation to work on.
105 * @param pvMutation Mutation dependent data.
106 * @param pfnExport The export callback.
107 * @param pvUser Opaque user data to pass to the export callback.
108 */
109typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXPORT(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
110 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
111/** Pointer to a mutator export callback. */
112typedef FNRTFUZZCTXMUTATOREXPORT *PFNRTFUZZCTXMUTATOREXPORT;
113
114
115/**
116 * Mutator import callback.
117 *
118 * @returns IPRT status code.
119 * @param pThis The fuzzer context instance.
120 * @param pMutation The mutation to work on.
121 * @param pvMutation Mutation dependent data.
122 * @param pfnExport The import callback.
123 * @param pvUser Opaque user data to pass to the import callback.
124 */
125typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATORIMPORT(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
126 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
127/** Pointer to a mutator import callback. */
128typedef FNRTFUZZCTXMUTATORIMPORT *PFNRTFUZZCTXMUTATORIMPORT;
129
130
131/**
132 * A fuzzing mutator descriptor.
133 */
134typedef struct RTFUZZMUTATOR
135{
136 /** Id of the mutator. */
137 const char *pszId;
138 /** Mutator description. */
139 const char *pszDesc;
140 /** Mutator index. */
141 uint32_t uMutator;
142 /** Additional flags for the mutator, controlling the behavior. */
143 uint64_t fFlags;
144 /** The preparation callback. */
145 PFNRTFUZZCTXMUTATORPREP pfnPrep;
146 /** The execution callback. */
147 PFNRTFUZZCTXMUTATOREXEC pfnExec;
148 /** The export callback. */
149 PFNRTFUZZCTXMUTATOREXPORT pfnExport;
150 /** The import callback. */
151 PFNRTFUZZCTXMUTATORIMPORT pfnImport;
152} RTFUZZMUTATOR;
153/** Pointer to a fuzzing mutator descriptor. */
154typedef RTFUZZMUTATOR *PRTFUZZMUTATOR;
155/** Pointer to a const fuzzing mutator descriptor. */
156typedef const RTFUZZMUTATOR *PCRTFUZZMUTATOR;
157
158/** The special corpus mutator. */
159#define RTFUZZMUTATOR_ID_CORPUS UINT32_C(0xffffffff)
160
161/** Mutator always works from the end of the buffer (no starting offset generation). */
162#define RTFUZZMUTATOR_F_END_OF_BUF RT_BIT_64(0)
163/** Default flags. */
164#define RTFUZZMUTATOR_F_DEFAULT (0)
165
166
167/**
168 * A fuzzed mutation.
169 */
170typedef struct RTFUZZMUTATION
171{
172 /** The AVL tree core. */
173 AVLU64NODECORE Core;
174 /** Magic identifying this structure. */
175 uint32_t u32Magic;
176 /** Reference counter. */
177 volatile uint32_t cRefs;
178 /** The fuzzer this mutation belongs to. */
179 PRTFUZZCTXINT pFuzzer;
180 /** Parent mutation (reference is held), NULL means root or original data. */
181 PCRTFUZZMUTATION pMutationParent;
182 /** Mutation level. */
183 uint32_t iLvl;
184 /** The mutator causing this mutation, NULL if original input data. */
185 PCRTFUZZMUTATOR pMutator;
186 /** Byte offset where the mutation starts. */
187 uint64_t offMutation;
188 /** Size of the generated input data in bytes after the mutation was applied. */
189 size_t cbInput;
190 /** Size of the mutation dependent data. */
191 size_t cbMutation;
192 /** Flag whether the mutation is contained in the tree of the context. */
193 bool fInTree;
194 /** Mutation dependent data, variable in size. */
195 uint8_t abMutation[1];
196} RTFUZZMUTATION;
197
198
199/**
200 * A fuzzing input seed.
201 */
202typedef struct RTFUZZINPUTINT
203{
204 /** Magic identifying this structure. */
205 uint32_t u32Magic;
206 /** Reference counter. */
207 volatile uint32_t cRefs;
208 /** The fuzzer this input belongs to. */
209 PRTFUZZCTXINT pFuzzer;
210 /** The top mutation to work from (reference held). */
211 PRTFUZZMUTATION pMutationTop;
212 /** Fuzzer context type dependent data. */
213 union
214 {
215 /** Blob data. */
216 struct
217 {
218 /** Size to allocate initially. */
219 size_t cbAlloc;
220 /** Input data size. */
221 size_t cbInput;
222 /** Pointer to the input data if created. */
223 void *pvInput;
224 } Blob;
225 /** Stream state. */
226 struct
227 {
228 /** Number of bytes seen so far. */
229 size_t cbSeen;
230 } Stream;
231 } u;
232 /** Array holding all the individual mutations, variable in size. */
233 PCRTFUZZMUTATION apMutations[1];
234} RTFUZZINPUTINT;
235/** Pointer to the internal input state. */
236typedef RTFUZZINPUTINT *PRTFUZZINPUTINT;
237/** Pointer to an internal input state pointer. */
238typedef PRTFUZZINPUTINT *PPRTFUZZINPUTINT;
239
240
241/**
242 * The fuzzer state.
243 */
244typedef struct RTFUZZCTXINT
245{
246 /** Magic value for identification. */
247 uint32_t u32Magic;
248 /** Reference counter. */
249 volatile uint32_t cRefs;
250 /** The random number generator. */
251 RTRAND hRand;
252 /** Fuzzing context type. */
253 RTFUZZCTXTYPE enmType;
254 /** Semaphore protecting the mutations tree. */
255 RTSEMRW hSemRwMutations;
256 /** The AVL tree for indexing the mutations (keyed by counter). */
257 AVLU64TREE TreeMutations;
258 /** Number of inputs currently in the tree. */
259 volatile uint64_t cMutations;
260 /** The maximum size of one input seed to generate. */
261 size_t cbInputMax;
262 /** Behavioral flags. */
263 uint32_t fFlagsBehavioral;
264 /** Number of enabled mutators. */
265 uint32_t cMutators;
266 /** Pointer to the mutator descriptors. */
267 PRTFUZZMUTATOR paMutators;
268 /** Total number of bytes of memory currently allocated in total for this context. */
269 volatile size_t cbMemTotal;
270} RTFUZZCTXINT;
271
272
273/**
274 * The fuzzer state to be exported - all members are stored in little endian form.
275 */
276typedef struct RTFUZZCTXSTATE
277{
278 /** Magic value for identification. */
279 uint32_t u32Magic;
280 /** Context type. */
281 uint32_t uCtxType;
282 /** Size of the PRNG state following in bytes. */
283 uint32_t cbPrng;
284 /** Number of mutator descriptors following. */
285 uint32_t cMutators;
286 /** Number of mutation descriptors following. */
287 uint32_t cMutations;
288 /** Behavioral flags. */
289 uint32_t fFlagsBehavioral;
290 /** Maximum input size to generate. */
291 uint64_t cbInputMax;
292} RTFUZZCTXSTATE;
293/** Pointer to a fuzzing context state. */
294typedef RTFUZZCTXSTATE *PRTFUZZCTXSTATE;
295
296/** BLOB context type. */
297#define RTFUZZCTX_STATE_TYPE_BLOB UINT32_C(0)
298/** Stream context type. */
299#define RTFUZZCTX_STATE_TYPE_STREAM UINT32_C(1)
300
301
302/**
303 * The fuzzer mutation state to be exported - all members are stored in little endian form.
304 */
305typedef struct RTFUZZMUTATIONSTATE
306{
307 /** The mutation identifier. */
308 uint64_t u64Id;
309 /** The mutation identifier of the parent, 0 for no parent. */
310 uint64_t u64IdParent;
311 /** The byte offset where the mutation starts. */
312 uint64_t u64OffMutation;
313 /** Size of input data after mutation was applied. */
314 uint64_t cbInput;
315 /** Size of mutation dependent data following. */
316 uint64_t cbMutation;
317 /** The mutator ID. */
318 uint32_t u32IdMutator;
319 /** The mutation level. */
320 uint32_t iLvl;
321 /** Magic value for identification. */
322 uint32_t u32Magic;
323} RTFUZZMUTATIONSTATE;
324
325
326/**
327 * Fuzzing context memory header.
328 */
329typedef struct RTFUZZMEMHDR
330{
331 /** Size of the memory area following. */
332 size_t cb;
333#if HC_ARCH_BITS == 32
334 /** Some padding. */
335 uint32_t uPadding0;
336#elif HC_ARCH_BITS == 64
337#else
338 /** Some padding. */
339 uint64_t uPadding0;
340# error "Port me"
341#endif
342} RTFUZZMEMHDR;
343/** Pointer to a memory header. */
344typedef RTFUZZMEMHDR *PRTFUZZMEMHDR;
345
346
347/**
348 * Fuzzing context export AVL arguments.
349 */
350typedef struct RTFUZZEXPORTARGS
351{
352 /** Pointer to the export callback. */
353 PFNRTFUZZCTXEXPORT pfnExport;
354 /** Opaque user data to pass to the callback. */
355 void *pvUser;
356} RTFUZZEXPORTARGS;
357/** Pointer to the export arguments. */
358typedef RTFUZZEXPORTARGS *PRTFUZZEXPORTARGS;
359/** Pointer to the constant export arguments. */
360typedef const RTFUZZEXPORTARGS *PCRTFUZZEXPORTARGS;
361
362
363/*********************************************************************************************************************************
364* Internal Functions *
365*********************************************************************************************************************************/
366static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
367 PPRTFUZZMUTATION ppMutation);
368static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
369 PPRTFUZZMUTATION ppMutation);
370static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
371 PPRTFUZZMUTATION ppMutation);
372static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
373 PPRTFUZZMUTATION ppMutation);
374static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
375 PPRTFUZZMUTATION ppMutation);
376static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
377 PPRTFUZZMUTATION ppMutation);
378
379static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
380 uint8_t *pbBuf, size_t cbBuf);
381static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
382 uint8_t *pbBuf, size_t cbBuf);
383static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
384 uint8_t *pbBuf, size_t cbBuf);
385static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
386 uint8_t *pbBuf, size_t cbBuf);
387static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
388 uint8_t *pbBuf, size_t cbBuf);
389static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
390 uint8_t *pbBuf, size_t cbBuf);
391static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
392 uint8_t *pbBuf, size_t cbBuf);
393
394static DECLCALLBACK(int) rtFuzzCtxMutatorExportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
395 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
396static DECLCALLBACK(int) rtFuzzCtxMutatorImportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
397 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
398
399
400/*********************************************************************************************************************************
401* Global Variables *
402*********************************************************************************************************************************/
403/**
404 * The special corpus mutator for the original data.
405 */
406static RTFUZZMUTATOR const g_MutatorCorpus =
407{
408 /** pszId */
409 "Corpus",
410 /** pszDesc */
411 "Special mutator, which is assigned to the initial corpus",
412 /** uMutator. */
413 RTFUZZMUTATOR_ID_CORPUS,
414 /** fFlags */
415 RTFUZZMUTATOR_F_DEFAULT,
416 /** pfnPrep */
417 NULL,
418 /** pfnExec */
419 rtFuzzCtxMutatorCorpusExec,
420 /** pfnExport */
421 rtFuzzCtxMutatorExportDefault,
422 /** pfnImport */
423 rtFuzzCtxMutatorImportDefault
424};
425
426/**
427 * Array of all available mutators.
428 */
429static RTFUZZMUTATOR const g_aMutators[] =
430{
431 /* pszId pszDesc uMutator fFlags pfnPrep pfnExec pfnExport pfnImport */
432 { "BitFlip", "Flips a single bit in the input", 0, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorBitFlipPrep, rtFuzzCtxMutatorBitFlipExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
433 { "ByteReplace", "Replaces a single byte in the input", 1, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteReplacePrep, rtFuzzCtxMutatorByteReplaceExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
434 { "ByteInsert", "Inserts a single byte sequence into the input", 2, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteInsertPrep, rtFuzzCtxMutatorByteInsertExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
435 { "ByteSeqIns", "Inserts a byte sequence in the input", 3, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
436 { "ByteSeqApp", "Appends a byte sequence to the input", 4, RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
437 { "ByteDelete", "Deletes a single byte sequence from the input", 5, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteDeletePrep, rtFuzzCtxMutatorByteDeleteExec, NULL, NULL },
438 { "ByteSeqDel", "Deletes a byte sequence from the input", 6, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceDeletePrep, rtFuzzCtxMutatorByteSequenceDeleteExec, NULL, NULL }
439};
440
441
442/**
443 * Allocates the given number of bytes.
444 *
445 * @returns Pointer to the allocated memory
446 * @param pThis The fuzzer context instance.
447 * @param cb How much to allocate.
448 */
449static void *rtFuzzCtxMemoryAlloc(PRTFUZZCTXINT pThis, size_t cb)
450{
451 PRTFUZZMEMHDR pMemHdr = (PRTFUZZMEMHDR)RTMemAllocZ(cb + sizeof(RTFUZZMEMHDR));
452 if (RT_LIKELY(pMemHdr))
453 {
454 pMemHdr->cb = cb;
455 size_t cbIgn = ASMAtomicAddZ(&pThis->cbMemTotal, cb + sizeof(RTFUZZMEMHDR)); RT_NOREF(cbIgn);
456 return pMemHdr + 1;
457 }
458
459 return NULL;
460}
461
462
463/**
464 * Frees the given memory.
465 *
466 * @returns nothing.
467 * @param pThis The fuzzer context instance.
468 * @param pv Pointer to the memory area to free.
469 */
470static void rtFuzzCtxMemoryFree(PRTFUZZCTXINT pThis, void *pv)
471{
472 PRTFUZZMEMHDR pMemHdr = ((PRTFUZZMEMHDR)pv) - 1;
473
474 size_t cbIgn = ASMAtomicSubZ(&pThis->cbMemTotal, pMemHdr->cb + sizeof(RTFUZZMEMHDR)); RT_NOREF(cbIgn);
475 RTMemFree(pMemHdr);
476}
477
478
479/**
480 * Destroys the given mutation.
481 *
482 * @returns nothing.
483 * @param pMutation The mutation to destroy.
484 */
485static void rtFuzzMutationDestroy(PRTFUZZMUTATION pMutation)
486{
487 rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation);
488}
489
490
491/**
492 * Retains an external reference to the given mutation.
493 *
494 * @returns New reference count on success.
495 * @param pMutation The mutation to retain.
496 */
497static uint32_t rtFuzzMutationRetain(PRTFUZZMUTATION pMutation)
498{
499 uint32_t cRefs = ASMAtomicIncU32(&pMutation->cRefs);
500 AssertMsg( ( cRefs > 1
501 || pMutation->fInTree)
502 && cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
503 return cRefs;
504}
505
506
507/**
508 * Releases an external reference from the given mutation.
509 *
510 * @returns New reference count on success.
511 * @param pMutation The mutation to retain.
512 */
513static uint32_t rtFuzzMutationRelease(PRTFUZZMUTATION pMutation)
514{
515 uint32_t cRefs = ASMAtomicDecU32(&pMutation->cRefs);
516 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
517 if (cRefs == 0 && !pMutation->fInTree)
518 rtFuzzMutationDestroy(pMutation);
519 return cRefs;
520}
521
522
523/**
524 * Adds the given mutation to the corpus of the given fuzzer context.
525 *
526 * @returns IPRT status code.
527 * @param pThis The fuzzer context instance.
528 * @param pMutation The mutation to add.
529 */
530static int rtFuzzCtxMutationAdd(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation)
531{
532 int rc = VINF_SUCCESS;
533
534 pMutation->Core.Key = ASMAtomicIncU64(&pThis->cMutations);
535 rc = RTSemRWRequestWrite(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
536 AssertRC(rc); RT_NOREF(rc);
537 bool fIns = RTAvlU64Insert(&pThis->TreeMutations, &pMutation->Core);
538 Assert(fIns); RT_NOREF(fIns);
539 rc = RTSemRWReleaseWrite(pThis->hSemRwMutations);
540 AssertRC(rc); RT_NOREF(rc);
541
542 pMutation->fInTree = true;
543 return rc;
544}
545
546
547/**
548 * Returns a random mutation from the corpus of the given fuzzer context.
549 *
550 * @returns Pointer to a randomly picked mutation (reference count is increased).
551 * @param pThis The fuzzer context instance.
552 */
553static PRTFUZZMUTATION rtFuzzCtxMutationPickRnd(PRTFUZZCTXINT pThis)
554{
555 uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 1, ASMAtomicReadU64(&pThis->cMutations));
556
557 int rc = RTSemRWRequestRead(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
558 AssertRC(rc); RT_NOREF(rc);
559
560 /*
561 * Using best fit getter here as there might be a racing mutation insertion and the mutation counter has increased
562 * already but the mutation is not yet in the tree.
563 */
564 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)RTAvlU64GetBestFit(&pThis->TreeMutations, idxMutation, false /*fAbove*/);
565 AssertPtr(pMutation);
566
567 /* Increase reference count of the mutation. */
568 rtFuzzMutationRetain(pMutation);
569 rc = RTSemRWReleaseRead(pThis->hSemRwMutations);
570 AssertRC(rc); RT_NOREF(rc);
571
572 return pMutation;
573}
574
575
576/**
577 * Creates a new mutation capable of holding the additional number of bytes.
578 *
579 * @returns Pointer to the newly created mutation or NULL if out of memory.
580 * @param pThis The fuzzer context instance.
581 * @param offMutation The starting offset for the mutation.
582 * @param pMutationParent The parent mutation, can be NULL.
583 * @param cbAdditional Additional number of bytes to allocate after the core structure.
584 * @param ppvMutation Where to store the pointer to the mutation dependent data on success.
585 */
586static PRTFUZZMUTATION rtFuzzMutationCreate(PRTFUZZCTXINT pThis, uint64_t offMutation, PRTFUZZMUTATION pMutationParent,
587 size_t cbAdditional, void **ppvMutation)
588{
589 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)rtFuzzCtxMemoryAlloc(pThis, sizeof(RTFUZZMUTATION) + cbAdditional);
590 if (RT_LIKELY(pMutation))
591 {
592 pMutation->u32Magic = 0; /** @todo */
593 pMutation->pFuzzer = pThis;
594 pMutation->cRefs = 1;
595 pMutation->iLvl = 0;
596 pMutation->offMutation = offMutation;
597 pMutation->pMutationParent = pMutationParent;
598 pMutation->cbMutation = cbAdditional;
599 pMutation->fInTree = false;
600
601 if (pMutationParent)
602 pMutation->iLvl = pMutationParent->iLvl + 1;
603 if (ppvMutation)
604 *ppvMutation = &pMutation->abMutation[0];
605 }
606
607 return pMutation;
608}
609
610
611/**
612 * Destorys the given fuzzer context freeing all allocated resources.
613 *
614 * @returns nothing.
615 * @param pThis The fuzzer context instance.
616 */
617static void rtFuzzCtxDestroy(PRTFUZZCTXINT pThis)
618{
619 RT_NOREF(pThis);
620}
621
622
623/**
624 * Default mutator export callback (just writing the raw data).
625 */
626static DECLCALLBACK(int) rtFuzzCtxMutatorExportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
627 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser)
628{
629 return pfnExport(pThis, pvMutation, pMutation->cbMutation, pvUser);
630}
631
632
633/**
634 * Default mutator import callback (just reading the raw data).
635 */
636static DECLCALLBACK(int) rtFuzzCtxMutatorImportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
637 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser)
638{
639 return pfnImport(pThis, pvMutation, pMutation->cbMutation, NULL, pvUser);
640}
641
642
643static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
644 uint8_t *pbBuf, size_t cbBuf)
645{
646 RT_NOREF(pThis, cbBuf, pvMutation);
647 memcpy(pbBuf, pvMutation, pMutation->cbInput);
648 return VINF_SUCCESS;
649}
650
651
652/**
653 * Mutator callback - flips a single bit in the input.
654 */
655static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
656 PPRTFUZZMUTATION ppMutation)
657{
658 int rc = VINF_SUCCESS;
659 uint8_t *pidxBitFlip = 0;
660 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pidxBitFlip), (void **)&pidxBitFlip);
661 if (RT_LIKELY(pMutation))
662 {
663 pMutation->cbInput = pMutationParent->cbInput; /* Bit flips don't change the input size. */
664 *pidxBitFlip = (uint8_t)RTRandAdvU32Ex(pThis->hRand, 0, sizeof(uint8_t) * 8 - 1);
665 *ppMutation = pMutation;
666 }
667 else
668 rc = VERR_NO_MEMORY;
669
670 return rc;
671}
672
673
674static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
675 uint8_t *pbBuf, size_t cbBuf)
676{
677 RT_NOREF(pThis, cbBuf, pMutation);
678 uint8_t idxBitFlip = *(uint8_t *)pvMutation;
679 ASMBitToggle(pbBuf, idxBitFlip);
680 return VINF_SUCCESS;
681}
682
683
684/**
685 * Mutator callback - replaces a single byte in the input.
686 */
687static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
688 PPRTFUZZMUTATION ppMutation)
689{
690 int rc = VINF_SUCCESS;
691 uint8_t *pbReplace = 0;
692 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pbReplace), (void **)&pbReplace);
693 if (RT_LIKELY(pMutation))
694 {
695 pMutation->cbInput = pMutationParent->cbInput; /* Byte replacements don't change the input size. */
696 RTRandAdvBytes(pThis->hRand, pbReplace, 1); /** @todo Filter out same values. */
697 *ppMutation = pMutation;
698 }
699 else
700 rc = VERR_NO_MEMORY;
701
702 return rc;
703}
704
705
706static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
707 uint8_t *pbBuf, size_t cbBuf)
708{
709 RT_NOREF(pThis, cbBuf, pMutation);
710 uint8_t bReplace = *(uint8_t *)pvMutation;
711 *pbBuf = bReplace;
712 return VINF_SUCCESS;
713}
714
715
716/**
717 * Mutator callback - inserts a single byte into the input.
718 */
719static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
720 PPRTFUZZMUTATION ppMutation)
721{
722 int rc = VINF_SUCCESS;
723 uint8_t *pbInsert = 0;
724 if (pMutationParent->cbInput < pThis->cbInputMax)
725 {
726 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 1 /*cbAdditional*/, (void **)&pbInsert);
727 if (RT_LIKELY(pMutation))
728 {
729 pMutation->cbInput = pMutationParent->cbInput + 1;
730 RTRandAdvBytes(pThis->hRand, pbInsert, 1);
731 *ppMutation = pMutation;
732 }
733 else
734 rc = VERR_NO_MEMORY;
735 }
736
737 return rc;
738}
739
740
741static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
742 uint8_t *pbBuf, size_t cbBuf)
743{
744 RT_NOREF(pThis, pMutation, pvMutation);
745
746 /* Just move the residual data one byte to the back. */
747 memmove(pbBuf + 1, pbBuf, cbBuf);
748 *pbBuf = *(uint8_t *)pvMutation;
749 return VINF_SUCCESS;
750}
751
752
753/**
754 * Mutator callback - inserts a byte sequence into the input.
755 */
756static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
757 PPRTFUZZMUTATION ppMutation)
758{
759 int rc = VINF_SUCCESS;
760 if (pMutationParent->cbInput < pThis->cbInputMax)
761 {
762 size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, pMutationParent->cbInput + 1, pThis->cbInputMax);
763 size_t cbInsert = cbInputMutated - pMutationParent->cbInput;
764 uint8_t *pbAdd = NULL;
765
766 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, cbInsert, (void **)&pbAdd);
767 if (RT_LIKELY(pMutation))
768 {
769 pMutation->cbInput = cbInputMutated;
770 RTRandAdvBytes(pThis->hRand, pbAdd, cbInsert);
771 *ppMutation = pMutation;
772 }
773 else
774 rc = VERR_NO_MEMORY;
775 }
776
777 return rc;
778}
779
780
781static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
782 uint8_t *pbBuf, size_t cbBuf)
783{
784 RT_NOREF(pThis);
785 size_t cbInsert = pMutation->cbInput - pMutation->pMutationParent->cbInput;
786
787 /* Move any remaining data to the end. */
788 if (cbBuf)
789 memmove(pbBuf + cbInsert, pbBuf, cbBuf);
790
791 memcpy(pbBuf, pvMutation, cbInsert);
792 return VINF_SUCCESS;
793}
794
795
796/**
797 * Mutator callback - deletes a single byte in the input.
798 */
799static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
800 PPRTFUZZMUTATION ppMutation)
801{
802 int rc = VINF_SUCCESS;
803 if (pMutationParent->cbInput - offStart >= 1)
804 {
805 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/, NULL);
806 if (RT_LIKELY(pMutation))
807 {
808 pMutation->cbInput = pMutationParent->cbInput - 1;
809 *ppMutation = pMutation;
810 }
811 else
812 rc = VERR_NO_MEMORY;
813 }
814
815 return rc;
816}
817
818
819static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
820 uint8_t *pbBuf, size_t cbBuf)
821{
822 RT_NOREF(pThis, pMutation, pvMutation);
823
824 /* Just move the residual data to the front. */
825 memmove(pbBuf, pbBuf + 1, cbBuf - 1);
826 return VINF_SUCCESS;
827}
828
829
830
831/**
832 * Mutator callback - deletes a byte sequence in the input.
833 */
834static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
835 PPRTFUZZMUTATION ppMutation)
836{
837 int rc = VINF_SUCCESS;
838 if (pMutationParent->cbInput > offStart)
839 {
840 size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, offStart, pMutationParent->cbInput - 1);
841
842 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/, NULL);
843 if (RT_LIKELY(pMutation))
844 {
845 pMutation->cbInput = cbInputMutated;
846 *ppMutation = pMutation;
847 }
848 else
849 rc = VERR_NO_MEMORY;
850 }
851
852 return rc;
853}
854
855
856static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
857 uint8_t *pbBuf, size_t cbBuf)
858{
859 RT_NOREF(pThis, pvMutation);
860 Assert(pMutation->pMutationParent->cbInput > pMutation->cbInput);
861 size_t cbDel = pMutation->pMutationParent->cbInput - pMutation->cbInput;
862
863 /* Just move the residual data to the front. */
864 memmove(pbBuf, pbBuf + cbDel, cbBuf - cbDel);
865 return VINF_SUCCESS;
866}
867
868
869/**
870 * Creates an empty fuzzing context.
871 *
872 * @returns IPRT status code.
873 * @param ppThis Where to store the pointer to the internal fuzzing context instance on success.
874 * @param enmType Fuzzing context type.
875 */
876static int rtFuzzCtxCreateEmpty(PRTFUZZCTXINT *ppThis, RTFUZZCTXTYPE enmType)
877{
878 int rc;
879 PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis));
880 if (RT_LIKELY(pThis))
881 {
882 pThis->u32Magic = RTFUZZCTX_MAGIC;
883 pThis->cRefs = 1;
884 pThis->enmType = enmType;
885 pThis->TreeMutations = NULL;
886 pThis->cbInputMax = UINT32_MAX;
887 pThis->cMutations = 0;
888 pThis->fFlagsBehavioral = 0;
889 pThis->cbMemTotal = 0;
890
891 /* Copy the default mutator descriptors over. */
892 pThis->paMutators = (PRTFUZZMUTATOR)RTMemAllocZ(RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR));
893 if (RT_LIKELY(pThis->paMutators))
894 {
895 pThis->cMutators = RT_ELEMENTS(g_aMutators);
896 memcpy(&pThis->paMutators[0], &g_aMutators[0], RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR));
897
898 rc = RTSemRWCreate(&pThis->hSemRwMutations);
899 if (RT_SUCCESS(rc))
900 {
901 rc = RTRandAdvCreateParkMiller(&pThis->hRand);
902 if (RT_SUCCESS(rc))
903 {
904 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS());
905 *ppThis = pThis;
906 return VINF_SUCCESS;
907 }
908
909 RTSemRWDestroy(pThis->hSemRwMutations);
910 }
911 }
912 else
913 rc = VERR_NO_MEMORY;
914
915 RTMemFree(pThis);
916 }
917 else
918 rc = VERR_NO_MEMORY;
919
920 return rc;
921}
922
923
924/**
925 * Destroys the given fuzzing input.
926 *
927 * @returns nothing.
928 * @param pThis The fuzzing input to destroy.
929 */
930static void rtFuzzInputDestroy(PRTFUZZINPUTINT pThis)
931{
932 PRTFUZZCTXINT pFuzzer = pThis->pFuzzer;
933
934 if ( pFuzzer->enmType == RTFUZZCTXTYPE_BLOB
935 && pThis->u.Blob.pvInput)
936 rtFuzzCtxMemoryFree(pFuzzer, pThis->u.Blob.pvInput);
937
938 rtFuzzMutationRelease(pThis->pMutationTop);
939 rtFuzzCtxMemoryFree(pFuzzer, pThis);
940 RTFuzzCtxRelease(pFuzzer);
941}
942
943
944/**
945 * Creates the final input data applying all accumulated mutations.
946 *
947 * @returns IPRT status code.
948 * @param pThis The fuzzing input to finalize.
949 */
950static int rtFuzzInputDataFinalize(PRTFUZZINPUTINT pThis)
951{
952 Assert(!pThis->u.Blob.pvInput);
953
954 int rc = VINF_SUCCESS;
955 uint8_t *pbBuf = (uint8_t *)rtFuzzCtxMemoryAlloc(pThis->pFuzzer, pThis->u.Blob.cbAlloc);
956 if (RT_LIKELY(pbBuf))
957 {
958 pThis->u.Blob.pvInput = pbBuf;
959 pThis->u.Blob.cbInput = pThis->pMutationTop->cbInput;
960
961 size_t cbInputNow = pThis->apMutations[0]->cbInput;
962 for (uint32_t i = 0; i < pThis->pMutationTop->iLvl + 1; i++)
963 {
964 PCRTFUZZMUTATION pMutation = pThis->apMutations[i];
965 pMutation->pMutator->pfnExec(pThis->pFuzzer, pMutation, (void *)&pMutation->abMutation[0],
966 pbBuf + pMutation->offMutation,
967 cbInputNow - pMutation->offMutation);
968
969 cbInputNow = pMutation->cbInput;
970 }
971
972 Assert(cbInputNow == pThis->u.Blob.cbInput);
973 }
974 else
975 rc = VERR_NO_MEMORY;
976
977 return rc;
978}
979
980
981RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx, RTFUZZCTXTYPE enmType)
982{
983 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
984
985 return rtFuzzCtxCreateEmpty(phFuzzCtx, enmType);
986}
987
988
989RTDECL(int) RTFuzzCtxCreateFromState(PRTFUZZCTX phFuzzCtx, PFNRTFUZZCTXIMPORT pfnImport, void *pvUser)
990{
991 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
992 AssertPtrReturn(pfnImport, VERR_INVALID_POINTER);
993
994#if 0
995 int rc = VINF_SUCCESS;
996 if (cbState >= sizeof(RTFUZZCTXSTATE))
997 {
998 RTFUZZCTXSTATE StateImport;
999
1000 memcpy(&StateImport, pvState, sizeof(RTFUZZCTXSTATE));
1001 if ( RT_LE2H_U32(StateImport.u32Magic) == RTFUZZCTX_MAGIC
1002 && RT_LE2H_U32(StateImport.cbPrng) <= cbState - sizeof(RTFUZZCTXSTATE))
1003 {
1004 PRTFUZZCTXINT pThis = rtFuzzCtxCreateEmpty();
1005 if (RT_LIKELY(pThis))
1006 {
1007 pThis->cbInputMax = (size_t)RT_LE2H_U64(StateImport.cbInputMax);
1008 pThis->fFlagsBehavioral = RT_LE2H_U32(StateImport.fFlagsBehavioral);
1009
1010 uint8_t *pbState = (uint8_t *)pvState;
1011 uint32_t cInputs = RT_LE2H_U32(StateImport.cInputs);
1012 rc = RTRandAdvRestoreState(pThis->hRand, (const char *)&pbState[sizeof(RTFUZZCTXSTATE)]);
1013 if (RT_SUCCESS(rc))
1014 {
1015 /* Go through the inputs and add them. */
1016 pbState += sizeof(RTFUZZCTXSTATE) + RT_LE2H_U32(StateImport.cbPrng);
1017 cbState -= sizeof(RTFUZZCTXSTATE) + RT_LE2H_U32(StateImport.cbPrng);
1018
1019 uint32_t idx = 0;
1020 while ( idx < cInputs
1021 && RT_SUCCESS(rc))
1022 {
1023 size_t cbInput = 0;
1024 if (cbState >= sizeof(uint32_t))
1025 {
1026 memcpy(&cbInput, pbState, sizeof(uint32_t));
1027 cbInput = RT_LE2H_U32(cbInput);
1028 pbState += sizeof(uint32_t);
1029 }
1030
1031 if ( cbInput
1032 && cbInput <= cbState)
1033 {
1034 PRTFUZZINPUTINT pInput = rtFuzzCtxInputCreate(pThis, cbInput);
1035 if (RT_LIKELY(pInput))
1036 {
1037 memcpy(&pInput->abInput[0], pbState, cbInput);
1038 RTMd5(&pInput->abInput[0], pInput->cbInput, &pInput->abMd5Hash[0]);
1039 rc = rtFuzzCtxInputAdd(pThis, pInput);
1040 if (RT_FAILURE(rc))
1041 RTMemFree(pInput);
1042 pbState += cbInput;
1043 }
1044 }
1045 else
1046 rc = VERR_INVALID_STATE;
1047
1048 idx++;
1049 }
1050
1051 if (RT_SUCCESS(rc))
1052 {
1053 *phFuzzCtx = pThis;
1054 return VINF_SUCCESS;
1055 }
1056 }
1057
1058 rtFuzzCtxDestroy(pThis);
1059 }
1060 else
1061 rc = VERR_NO_MEMORY;
1062 }
1063 else
1064 rc = VERR_INVALID_MAGIC;
1065 }
1066 else
1067 rc = VERR_INVALID_MAGIC;
1068
1069 return rc;
1070#else
1071 RT_NOREF(pvUser);
1072 return VERR_NOT_IMPLEMENTED;
1073#endif
1074}
1075
1076
1077RTDECL(int) RTFuzzCtxCreateFromStateMem(PRTFUZZCTX phFuzzCtx, const void *pvState, size_t cbState)
1078{
1079 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
1080 AssertPtrReturn(pvState, VERR_INVALID_POINTER);
1081 AssertPtrReturn(cbState, VERR_INVALID_POINTER);
1082
1083 return VERR_NOT_IMPLEMENTED;
1084}
1085
1086
1087RTDECL(int) RTFuzzCtxCreateFromStateFile(PRTFUZZCTX phFuzzCtx, const char *pszFilename)
1088{
1089 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
1090 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1091
1092 void *pv = NULL;
1093 size_t cb = 0;
1094 int rc = RTFileReadAll(pszFilename, &pv, &cb);
1095 if (RT_SUCCESS(rc))
1096 {
1097 rc = RTFuzzCtxCreateFromStateMem(phFuzzCtx, pv, cb);
1098 RTFileReadAllFree(pv, cb);
1099 }
1100
1101 return rc;
1102}
1103
1104
1105RTDECL(uint32_t) RTFuzzCtxRetain(RTFUZZCTX hFuzzCtx)
1106{
1107 PRTFUZZCTXINT pThis = hFuzzCtx;
1108
1109 AssertPtrReturn(pThis, UINT32_MAX);
1110
1111 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
1112 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
1113 return cRefs;
1114}
1115
1116
1117RTDECL(uint32_t) RTFuzzCtxRelease(RTFUZZCTX hFuzzCtx)
1118{
1119 PRTFUZZCTXINT pThis = hFuzzCtx;
1120 if (pThis == NIL_RTFUZZCTX)
1121 return 0;
1122 AssertPtrReturn(pThis, UINT32_MAX);
1123
1124 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
1125 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
1126 if (cRefs == 0)
1127 rtFuzzCtxDestroy(pThis);
1128 return cRefs;
1129}
1130
1131
1132/**
1133 * Fuzzing context export callback for a single mutation.
1134 */
1135static DECLCALLBACK(int) rtFuzzCtxStateExportMutations(PAVLU64NODECORE pCore, void *pvParam)
1136{
1137 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)pCore;
1138 PCRTFUZZMUTATOR pMutator = pMutation->pMutator;
1139 PCRTFUZZEXPORTARGS pArgs = (PCRTFUZZEXPORTARGS)pvParam;
1140 RTFUZZMUTATIONSTATE MutationState;
1141
1142 MutationState.u64Id = RT_H2LE_U64(pMutation->Core.Key);
1143 if (pMutation->pMutationParent)
1144 MutationState.u64IdParent = RT_H2LE_U64(pMutation->pMutationParent->Core.Key);
1145 else
1146 MutationState.u64IdParent = RT_H2LE_U64(0);
1147 MutationState.u64OffMutation = RT_H2LE_U64(pMutation->offMutation);
1148 MutationState.cbInput = RT_H2LE_U64((uint64_t)pMutation->cbInput);
1149 MutationState.cbMutation = RT_H2LE_U64((uint64_t)pMutation->cbMutation);
1150 MutationState.u32IdMutator = RT_H2LE_U32(pMutator->uMutator);
1151 MutationState.iLvl = RT_H2LE_U32(pMutation->iLvl);
1152 MutationState.u32Magic = RT_H2LE_U32(pMutation->u32Magic);
1153
1154 int rc = pArgs->pfnExport(pMutation->pFuzzer, &MutationState, sizeof(MutationState), pArgs->pvUser);
1155 if ( RT_SUCCESS(rc)
1156 && pMutator->pfnExport)
1157 rc = pMutator->pfnExport(pMutation->pFuzzer, pMutation, &pMutation->abMutation[0], pArgs->pfnExport, pArgs->pvUser);
1158 return rc;
1159}
1160
1161
1162RTDECL(int) RTFuzzCtxStateExport(RTFUZZCTX hFuzzCtx, PFNRTFUZZCTXEXPORT pfnExport, void *pvUser)
1163{
1164 PRTFUZZCTXINT pThis = hFuzzCtx;
1165 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1166 AssertPtrReturn(pfnExport, VERR_INVALID_POINTER);
1167
1168 char aszPrngExport[_4K]; /* Should be plenty of room here. */
1169 size_t cbPrng = sizeof(aszPrngExport);
1170 int rc = RTRandAdvSaveState(pThis->hRand, &aszPrngExport[0], &cbPrng);
1171 if (RT_SUCCESS(rc))
1172 {
1173 RTFUZZCTXSTATE StateExport;
1174
1175 StateExport.u32Magic = RT_H2LE_U32(RTFUZZCTX_MAGIC);
1176 switch (pThis->enmType)
1177 {
1178 case RTFUZZCTXTYPE_BLOB:
1179 StateExport.uCtxType = RT_H2LE_U32(RTFUZZCTX_STATE_TYPE_BLOB);
1180 break;
1181 case RTFUZZCTXTYPE_STREAM:
1182 StateExport.uCtxType = RT_H2LE_U32(RTFUZZCTX_STATE_TYPE_STREAM);
1183 break;
1184 default:
1185 AssertFailed();
1186 break;
1187 }
1188 StateExport.cbPrng = RT_H2LE_U32((uint32_t)cbPrng);
1189 StateExport.cMutations = RT_H2LE_U32(pThis->cMutations);
1190 StateExport.cMutators = RT_H2LE_U32(pThis->cMutators);
1191 StateExport.fFlagsBehavioral = RT_H2LE_U32(pThis->fFlagsBehavioral);
1192 StateExport.cbInputMax = RT_H2LE_U64(pThis->cbInputMax);
1193
1194 /* Write the context state and PRNG state first. */
1195 rc = pfnExport(pThis, &StateExport, sizeof(StateExport), pvUser);
1196 if (RT_SUCCESS(rc))
1197 rc = pfnExport(pThis, &aszPrngExport[0], cbPrng, pvUser);
1198 if (RT_SUCCESS(rc))
1199 {
1200 /* Write the mutator descriptors next. */
1201 for (uint32_t i = 0; i < pThis->cMutators && RT_SUCCESS(rc); i++)
1202 {
1203 PRTFUZZMUTATOR pMutator = &pThis->paMutators[i];
1204 uint32_t cchId = (uint32_t)strlen(pMutator->pszId) + 1;
1205 uint32_t cchIdW = RT_H2LE_U32(cchId);
1206
1207 rc = pfnExport(pThis, &cchIdW, sizeof(cchIdW), pvUser);
1208 if (RT_SUCCESS(rc))
1209 rc = pfnExport(pThis, &pMutator->pszId[0], cchId, pvUser);
1210 }
1211 }
1212
1213 /* Write the mutations last. */
1214 if (RT_SUCCESS(rc))
1215 {
1216 RTFUZZEXPORTARGS Args;
1217
1218 Args.pfnExport = pfnExport;
1219 Args.pvUser = pvUser;
1220 rc = RTAvlU64DoWithAll(&pThis->TreeMutations, true /*fFromLeft*/, rtFuzzCtxStateExportMutations, &Args);
1221 }
1222 }
1223
1224 return rc;
1225}
1226
1227
1228RTDECL(int) RTFuzzCtxStateExportToMem(RTFUZZCTX hFuzzCtx, void **ppvState, size_t *pcbState)
1229{
1230 PRTFUZZCTXINT pThis = hFuzzCtx;
1231 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1232 AssertPtrReturn(ppvState, VERR_INVALID_POINTER);
1233 AssertPtrReturn(pcbState, VERR_INVALID_POINTER);
1234
1235 return VERR_NOT_IMPLEMENTED;
1236}
1237
1238
1239/**
1240 * Export to file callback.
1241 */
1242static DECLCALLBACK(int) rtFuzzCtxStateExportFile(RTFUZZCTX hFuzzCtx, const void *pvBuf, size_t cbWrite, void *pvUser)
1243{
1244 RT_NOREF(hFuzzCtx);
1245
1246 RTFILE hFile = (RTFILE)pvUser;
1247 return RTFileWrite(hFile, pvBuf, cbWrite, NULL);
1248}
1249
1250
1251RTDECL(int) RTFuzzCtxStateExportToFile(RTFUZZCTX hFuzzCtx, const char *pszFilename)
1252{
1253 PRTFUZZCTXINT pThis = hFuzzCtx;
1254 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1255 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1256
1257 RTFILE hFile;
1258 int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
1259 if (RT_SUCCESS(rc))
1260 {
1261 rc = RTFuzzCtxStateExport(hFuzzCtx, rtFuzzCtxStateExportFile, hFile);
1262 RTFileClose(hFile);
1263 if (RT_FAILURE(rc))
1264 RTFileDelete(pszFilename);
1265 }
1266
1267 return rc;
1268}
1269
1270
1271RTDECL(int) RTFuzzCtxCorpusInputAdd(RTFUZZCTX hFuzzCtx, const void *pvInput, size_t cbInput)
1272{
1273 PRTFUZZCTXINT pThis = hFuzzCtx;
1274 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1275 AssertPtrReturn(pvInput, VERR_INVALID_POINTER);
1276 AssertReturn(cbInput, VERR_INVALID_POINTER);
1277
1278 int rc = VINF_SUCCESS;
1279 void *pvCorpus = NULL;
1280 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbInput, &pvCorpus);
1281 if (RT_LIKELY(pMutation))
1282 {
1283 pMutation->pMutator = &g_MutatorCorpus;
1284 pMutation->cbInput = cbInput;
1285 memcpy(pvCorpus, pvInput, cbInput);
1286 rc = rtFuzzCtxMutationAdd(pThis, pMutation);
1287 if (RT_FAILURE(rc))
1288 rtFuzzMutationDestroy(pMutation);
1289 }
1290 else
1291 rc = VERR_NO_MEMORY;
1292
1293 return rc;
1294}
1295
1296
1297RTDECL(int) RTFuzzCtxCorpusInputAddFromFile(RTFUZZCTX hFuzzCtx, const char *pszFilename)
1298{
1299 PRTFUZZCTXINT pThis = hFuzzCtx;
1300 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1301 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1302
1303 void *pv = NULL;
1304 size_t cb = 0;
1305 int rc = RTFileReadAll(pszFilename, &pv, &cb);
1306 if (RT_SUCCESS(rc))
1307 {
1308 rc = RTFuzzCtxCorpusInputAdd(hFuzzCtx, pv, cb);
1309 RTFileReadAllFree(pv, cb);
1310 }
1311
1312 return rc;
1313}
1314
1315
1316RTDECL(int) RTFuzzCtxCorpusInputAddFromVfsFile(RTFUZZCTX hFuzzCtx, RTVFSFILE hVfsFile)
1317{
1318 PRTFUZZCTXINT pThis = hFuzzCtx;
1319 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1320 AssertReturn(hVfsFile != NIL_RTVFSFILE, VERR_INVALID_HANDLE);
1321
1322 uint64_t cbFile = 0;
1323 void *pvCorpus = NULL;
1324 int rc = RTVfsFileGetSize(hVfsFile, &cbFile);
1325 if (RT_SUCCESS(rc))
1326 {
1327 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbFile, &pvCorpus);
1328 if (RT_LIKELY(pMutation))
1329 {
1330 pMutation->pMutator = &g_MutatorCorpus;
1331 pMutation->cbInput = cbFile;
1332 rc = RTVfsFileRead(hVfsFile, pvCorpus, cbFile, NULL);
1333 if (RT_SUCCESS(rc))
1334 rc = rtFuzzCtxMutationAdd(pThis, pMutation);
1335
1336 if (RT_FAILURE(rc))
1337 rtFuzzMutationDestroy(pMutation);
1338 }
1339 }
1340
1341 return rc;
1342}
1343
1344
1345RTDECL(int) RTFuzzCtxCorpusInputAddFromDirPath(RTFUZZCTX hFuzzCtx, const char *pszDirPath)
1346{
1347 PRTFUZZCTXINT pThis = hFuzzCtx;
1348 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1349 AssertPtrReturn(pszDirPath, VERR_INVALID_POINTER);
1350
1351 RTDIR hDir;
1352 int rc = RTDirOpen(&hDir, pszDirPath);
1353 if (RT_SUCCESS(rc))
1354 {
1355 for (;;)
1356 {
1357 RTDIRENTRY DirEntry;
1358 rc = RTDirRead(hDir, &DirEntry, NULL);
1359 if (RT_FAILURE(rc))
1360 break;
1361
1362 /* Skip '.', '..' and other non-files. */
1363 if ( DirEntry.enmType != RTDIRENTRYTYPE_UNKNOWN
1364 && DirEntry.enmType != RTDIRENTRYTYPE_FILE)
1365 continue;
1366 if (RTDirEntryIsStdDotLink(&DirEntry))
1367 continue;
1368
1369 /* Compose the full path, result 'unknown' entries and skip non-files. */
1370 char szFile[RTPATH_MAX];
1371 RT_ZERO(szFile);
1372 rc = RTPathJoin(szFile, sizeof(szFile), pszDirPath, DirEntry.szName);
1373 if (RT_FAILURE(rc))
1374 break;
1375
1376 if (DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN)
1377 {
1378 RTDirQueryUnknownType(szFile, false, &DirEntry.enmType);
1379 if (DirEntry.enmType != RTDIRENTRYTYPE_FILE)
1380 continue;
1381 }
1382
1383 /* Okay, it's a file we can add. */
1384 rc = RTFuzzCtxCorpusInputAddFromFile(hFuzzCtx, szFile);
1385 if (RT_FAILURE(rc))
1386 break;
1387 }
1388 if (rc == VERR_NO_MORE_FILES)
1389 rc = VINF_SUCCESS;
1390 RTDirClose(hDir);
1391 }
1392
1393 return rc;
1394}
1395
1396
1397RTDECL(int) RTFuzzCtxCfgSetInputSeedMaximum(RTFUZZCTX hFuzzCtx, size_t cbMax)
1398{
1399 PRTFUZZCTXINT pThis = hFuzzCtx;
1400 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1401
1402 pThis->cbInputMax = cbMax;
1403 return VINF_SUCCESS;
1404}
1405
1406
1407RTDECL(size_t) RTFuzzCtxCfgGetInputSeedMaximum(RTFUZZCTX hFuzzCtx)
1408{
1409 PRTFUZZCTXINT pThis = hFuzzCtx;
1410 AssertPtrReturn(pThis, 0);
1411
1412 return pThis->cbInputMax;
1413}
1414
1415
1416RTDECL(int) RTFuzzCtxCfgSetBehavioralFlags(RTFUZZCTX hFuzzCtx, uint32_t fFlags)
1417{
1418 PRTFUZZCTXINT pThis = hFuzzCtx;
1419 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1420 AssertReturn(!(fFlags & ~RTFUZZCTX_F_BEHAVIORAL_VALID), VERR_INVALID_PARAMETER);
1421
1422 pThis->fFlagsBehavioral = fFlags;
1423 return VINF_SUCCESS;
1424}
1425
1426
1427RTDECL(uint32_t) RTFuzzCfgGetBehavioralFlags(RTFUZZCTX hFuzzCtx)
1428{
1429 PRTFUZZCTXINT pThis = hFuzzCtx;
1430 AssertPtrReturn(pThis, 0);
1431
1432 return pThis->fFlagsBehavioral;
1433}
1434
1435
1436RTDECL(int) RTFuzzCtxCfgSetTmpDirectory(RTFUZZCTX hFuzzCtx, const char *pszPathTmp)
1437{
1438 PRTFUZZCTXINT pThis = hFuzzCtx;
1439 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1440 AssertPtrReturn(pszPathTmp, VERR_INVALID_POINTER);
1441
1442 return VERR_NOT_IMPLEMENTED;
1443}
1444
1445
1446RTDECL(const char *) RTFuzzCtxCfgGetTmpDirectory(RTFUZZCTX hFuzzCtx)
1447{
1448 PRTFUZZCTXINT pThis = hFuzzCtx;
1449 AssertPtrReturn(pThis, NULL);
1450
1451 return NULL;
1452}
1453
1454
1455RTDECL(int) RTFuzzCtxReseed(RTFUZZCTX hFuzzCtx, uint64_t uSeed)
1456{
1457 PRTFUZZCTXINT pThis = hFuzzCtx;
1458 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1459
1460 RTRandAdvSeed(pThis->hRand, uSeed);
1461 return VINF_SUCCESS;
1462}
1463
1464
1465RTDECL(int) RTFuzzCtxInputGenerate(RTFUZZCTX hFuzzCtx, PRTFUZZINPUT phFuzzInput)
1466{
1467 int rc = VINF_SUCCESS;
1468 PRTFUZZCTXINT pThis = hFuzzCtx;
1469 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1470 AssertPtrReturn(phFuzzInput, VERR_INVALID_POINTER);
1471
1472 uint32_t cTries = 0;
1473 PRTFUZZMUTATION pMutationParent = rtFuzzCtxMutationPickRnd(pThis);
1474 do
1475 {
1476 uint32_t idxMutator = RTRandAdvU32Ex(pThis->hRand, 0, pThis->cMutators - 1);
1477 PCRTFUZZMUTATOR pMutator = &pThis->paMutators[idxMutator];
1478 PRTFUZZMUTATION pMutation = NULL;
1479
1480 uint64_t offStart = 0;
1481 if (!(pMutator->fFlags & RTFUZZMUTATOR_F_END_OF_BUF))
1482 offStart = RTRandAdvU64Ex(pThis->hRand, 0, pMutationParent->cbInput);
1483 else
1484 offStart = pMutationParent->cbInput;
1485
1486 rc = pMutator->pfnPrep(pThis, offStart, pMutationParent, &pMutation);
1487 if ( RT_SUCCESS(rc)
1488 && VALID_PTR(pMutation))
1489 {
1490 pMutation->pMutator = pMutator;
1491
1492 if (pThis->fFlagsBehavioral & RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS)
1493 rtFuzzCtxMutationAdd(pThis, pMutation);
1494
1495 /* Create a new input. */
1496 PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)rtFuzzCtxMemoryAlloc(pThis, RT_UOFFSETOF_DYN(RTFUZZINPUTINT, apMutations[pMutation->iLvl + 1]));
1497 if (RT_LIKELY(pInput))
1498 {
1499 pInput->u32Magic = 0; /** @todo */
1500 pInput->cRefs = 1;
1501 pInput->pFuzzer = pThis;
1502 pInput->pMutationTop = pMutation;
1503 RTFuzzCtxRetain(pThis);
1504
1505 /* Traverse the mutations top to bottom and insert into the array. */
1506 uint32_t idx = pMutation->iLvl + 1;
1507 PCRTFUZZMUTATION pMutationCur = pMutation;
1508 size_t cbAlloc = 0;
1509 while (idx > 0)
1510 {
1511 pInput->apMutations[idx - 1] = pMutationCur;
1512 cbAlloc = RT_MAX(cbAlloc, pMutationCur->cbInput);
1513 pMutationCur = pMutationCur->pMutationParent;
1514 idx--;
1515 }
1516
1517 pInput->u.Blob.cbAlloc = cbAlloc;
1518 *phFuzzInput = pInput;
1519 return rc;
1520 }
1521 else
1522 rc = VERR_NO_MEMORY;
1523 }
1524 } while (++cTries <= 50);
1525
1526 if (RT_SUCCESS(rc))
1527 rc = VERR_INVALID_STATE;
1528
1529 return rc;
1530}
1531
1532
1533RTDECL(int) RTFuzzInputQueryBlobData(RTFUZZINPUT hFuzzInput, void **ppv, size_t *pcb)
1534{
1535 PRTFUZZINPUTINT pThis = hFuzzInput;
1536 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1537 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
1538
1539 int rc = VINF_SUCCESS;
1540 if (!pThis->u.Blob.pvInput)
1541 rc = rtFuzzInputDataFinalize(pThis);
1542
1543 if (RT_SUCCESS(rc))
1544 {
1545 AssertPtr(pThis->u.Blob.pvInput);
1546 Assert(pThis->u.Blob.cbInput > 0);
1547
1548 *ppv = pThis->u.Blob.pvInput;
1549 *pcb = pThis->u.Blob.cbInput;
1550 }
1551
1552 return rc;
1553}
1554
1555
1556RTDECL(int) RTFuzzInputMutateStreamData(RTFUZZINPUT hFuzzInput, void *pvBuf, size_t cbBuf)
1557{
1558 PRTFUZZINPUTINT pThis = hFuzzInput;
1559 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1560 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_STREAM, VERR_INVALID_STATE);
1561
1562 RT_NOREF(pvBuf, cbBuf);
1563 return VERR_NOT_IMPLEMENTED;
1564}
1565
1566
1567RTDECL(uint32_t) RTFuzzInputRetain(RTFUZZINPUT hFuzzInput)
1568{
1569 PRTFUZZINPUTINT pThis = hFuzzInput;
1570
1571 AssertPtrReturn(pThis, UINT32_MAX);
1572
1573 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
1574 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
1575 return cRefs;
1576}
1577
1578
1579RTDECL(uint32_t) RTFuzzInputRelease(RTFUZZINPUT hFuzzInput)
1580{
1581 PRTFUZZINPUTINT pThis = hFuzzInput;
1582 if (pThis == NIL_RTFUZZINPUT)
1583 return 0;
1584 AssertPtrReturn(pThis, UINT32_MAX);
1585
1586 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
1587 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
1588 if (cRefs == 0)
1589 rtFuzzInputDestroy(pThis);
1590 return cRefs;
1591}
1592
1593
1594RTDECL(int) RTFuzzInputQueryDigestString(RTFUZZINPUT hFuzzInput, char *pszDigest, size_t cchDigest)
1595{
1596 PRTFUZZINPUTINT pThis = hFuzzInput;
1597 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1598 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
1599 AssertPtrReturn(pszDigest, VERR_INVALID_POINTER);
1600 AssertReturn(cchDigest >= RTMD5_STRING_LEN + 1, VERR_INVALID_PARAMETER);
1601
1602 int rc = VINF_SUCCESS;
1603 if (!pThis->u.Blob.pvInput)
1604 rc = rtFuzzInputDataFinalize(pThis);
1605
1606 if (RT_SUCCESS(rc))
1607 {
1608 uint8_t abHash[RTMD5_HASH_SIZE];
1609 RTMd5(pThis->u.Blob.pvInput, pThis->u.Blob.cbInput, &abHash[0]);
1610 rc = RTMd5ToString(&abHash[0], pszDigest, cchDigest);
1611 }
1612
1613 return rc;
1614}
1615
1616
1617RTDECL(int) RTFuzzInputWriteToFile(RTFUZZINPUT hFuzzInput, const char *pszFilename)
1618{
1619 PRTFUZZINPUTINT pThis = hFuzzInput;
1620 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1621 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
1622 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1623
1624 int rc = VINF_SUCCESS;
1625 if (!pThis->u.Blob.pvInput)
1626 rc = rtFuzzInputDataFinalize(pThis);
1627
1628 if (RT_SUCCESS(rc))
1629 {
1630 RTFILE hFile;
1631 rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
1632 if (RT_SUCCESS(rc))
1633 {
1634 rc = RTFileWrite(hFile, pThis->u.Blob.pvInput, pThis->u.Blob.cbInput, NULL);
1635 AssertRC(rc);
1636 RTFileClose(hFile);
1637
1638 if (RT_FAILURE(rc))
1639 RTFileDelete(pszFilename);
1640 }
1641 }
1642
1643 return rc;
1644}
1645
1646
1647RTDECL(int) RTFuzzInputAddToCtxCorpus(RTFUZZINPUT hFuzzInput)
1648{
1649 PRTFUZZINPUTINT pThis = hFuzzInput;
1650 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1651
1652 return rtFuzzCtxMutationAdd(pThis->pFuzzer, pThis->pMutationTop);
1653}
1654
1655
1656RTDECL(int) RTFuzzInputRemoveFromCtxCorpus(RTFUZZINPUT hFuzzInput)
1657{
1658 PRTFUZZINPUTINT pThis = hFuzzInput;
1659 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1660
1661#if 0
1662 int rc = VINF_SUCCESS;
1663 PRTFUZZINTERMEDIATE pIntermediate = NULL;
1664 PRTFUZZINPUTINT pInputLoc = rtFuzzCtxInputLocate(pThis->pFuzzer, &pThis->abMd5Hash[0], true /*fExact*/,
1665 &pIntermediate);
1666 if (pInputLoc)
1667 {
1668 AssertPtr(pIntermediate);
1669 Assert(pInputLoc == pThis);
1670
1671 uint64_t u64Md5Low = *(uint64_t *)&pThis->abMd5Hash[0];
1672 RTAvlU64Remove(&pIntermediate->TreeSeedsLow, u64Md5Low);
1673 RTFuzzInputRelease(hFuzzInput);
1674 }
1675 else
1676 rc = VERR_NOT_FOUND;
1677#endif
1678
1679 return VERR_NOT_IMPLEMENTED;
1680}
1681
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