VirtualBox

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

最後變更 在這個檔案從83266是 83266,由 vboxsync 提交於 5 年 前

Runtime/common/fuzz: Add API to specify the range in an input corpus where mutations are allowed, global and per input. Allows fuzzing certain interesting areas which might not be reached that often otherwise

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 80.4 KB
 
1/* $Id: fuzz.cpp 83266 2020-03-11 18:38:31Z vboxsync $ */
2/** @file
3 * IPRT - Fuzzing framework API, core.
4 */
5
6/*
7 * Copyright (C) 2018-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. 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/critsect.h>
38#include <iprt/ctype.h>
39#include <iprt/dir.h>
40#include <iprt/err.h>
41#include <iprt/file.h>
42#include <iprt/list.h>
43#include <iprt/md5.h>
44#include <iprt/mem.h>
45#include <iprt/path.h>
46#include <iprt/rand.h>
47#include <iprt/semaphore.h>
48#include <iprt/string.h>
49#include <iprt/time.h>
50#include <iprt/vfs.h>
51
52
53#define RTFUZZCTX_MAGIC UINT32_C(0xdeadc0de) /** @todo */
54
55
56/*********************************************************************************************************************************
57* Structures and Typedefs *
58*********************************************************************************************************************************/
59/** Pointer to the internal fuzzer state. */
60typedef struct RTFUZZCTXINT *PRTFUZZCTXINT;
61/** Pointer to a fuzzed mutation. */
62typedef struct RTFUZZMUTATION *PRTFUZZMUTATION;
63/** Pointer to a fuzzed mutation pointer. */
64typedef PRTFUZZMUTATION *PPRTFUZZMUTATION;
65/** Pointer to a const mutation. */
66typedef const struct RTFUZZMUTATION *PCRTFUZZMUTATION;
67
68
69/**
70 * Mutator class.
71 */
72typedef enum RTFUZZMUTATORCLASS
73{
74 /** Invalid class, do not use. */
75 RTFUZZMUTATORCLASS_INVALID = 0,
76 /** Mutator operates on single bits. */
77 RTFUZZMUTATORCLASS_BITS,
78 /** Mutator operates on bytes (single or multiple). */
79 RTFUZZMUTATORCLASS_BYTES,
80 /** Mutator interpretes data as integers and operates on them. */
81 RTFUZZMUTATORCLASS_INTEGERS,
82 /** Mutator uses multiple mutations to create new mutations. */
83 RTFUZZMUTATORCLASS_MUTATORS,
84 /** 32bit hack. */
85 RTFUZZMUTATORCLASS_32BIT_HACK = 0x7fffffff
86} RTFUZZMUTATORCLASS;
87
88
89/**
90 * Mutator preparation callback.
91 *
92 * @returns IPRT status code.
93 * @param pThis The fuzzer context instance.
94 * @param offStart Where the mutation should start.
95 * @param pMutationParent The parent mutation to start working from.
96 * @param ppMutation Where to store the created mutation on success.
97 */
98typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATORPREP(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
99 PPRTFUZZMUTATION ppMutation);
100/** Pointer to a mutator preparation callback. */
101typedef FNRTFUZZCTXMUTATORPREP *PFNRTFUZZCTXMUTATORPREP;
102
103
104/**
105 * Mutator execution callback.
106 *
107 * @returns IPRT status code.
108 * @param pThis The fuzzer context instance.
109 * @param pMutation The mutation to work on.
110 * @param pvMutation Mutation dependent data.
111 * @param pbBuf The buffer to work on.
112 * @param cbBuf Size of the remaining buffer.
113 */
114typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXEC(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
115 uint8_t *pbBuf, size_t cbBuf);
116/** Pointer to a mutator execution callback. */
117typedef FNRTFUZZCTXMUTATOREXEC *PFNRTFUZZCTXMUTATOREXEC;
118
119
120/**
121 * Mutator export callback.
122 *
123 * @returns IPRT status code.
124 * @param pThis The fuzzer context instance.
125 * @param pMutation The mutation to work on.
126 * @param pvMutation Mutation dependent data.
127 * @param pfnExport The export callback.
128 * @param pvUser Opaque user data to pass to the export callback.
129 */
130typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXPORT(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
131 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
132/** Pointer to a mutator export callback. */
133typedef FNRTFUZZCTXMUTATOREXPORT *PFNRTFUZZCTXMUTATOREXPORT;
134
135
136/**
137 * Mutator import callback.
138 *
139 * @returns IPRT status code.
140 * @param pThis The fuzzer context instance.
141 * @param pMutation The mutation to work on.
142 * @param pvMutation Mutation dependent data.
143 * @param pfnExport The import callback.
144 * @param pvUser Opaque user data to pass to the import callback.
145 */
146typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATORIMPORT(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
147 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
148/** Pointer to a mutator import callback. */
149typedef FNRTFUZZCTXMUTATORIMPORT *PFNRTFUZZCTXMUTATORIMPORT;
150
151
152/**
153 * A fuzzing mutator descriptor.
154 */
155typedef struct RTFUZZMUTATOR
156{
157 /** Id of the mutator. */
158 const char *pszId;
159 /** Mutator description. */
160 const char *pszDesc;
161 /** Mutator index. */
162 uint32_t uMutator;
163 /** Mutator class. */
164 RTFUZZMUTATORCLASS enmClass;
165 /** Additional flags for the mutator, controlling the behavior. */
166 uint64_t fFlags;
167 /** The preparation callback. */
168 PFNRTFUZZCTXMUTATORPREP pfnPrep;
169 /** The execution callback. */
170 PFNRTFUZZCTXMUTATOREXEC pfnExec;
171 /** The export callback. */
172 PFNRTFUZZCTXMUTATOREXPORT pfnExport;
173 /** The import callback. */
174 PFNRTFUZZCTXMUTATORIMPORT pfnImport;
175} RTFUZZMUTATOR;
176/** Pointer to a fuzzing mutator descriptor. */
177typedef RTFUZZMUTATOR *PRTFUZZMUTATOR;
178/** Pointer to a const fuzzing mutator descriptor. */
179typedef const RTFUZZMUTATOR *PCRTFUZZMUTATOR;
180
181/** The special corpus mutator. */
182#define RTFUZZMUTATOR_ID_CORPUS UINT32_C(0xffffffff)
183
184/** Mutator always works from the end of the buffer (no starting offset generation). */
185#define RTFUZZMUTATOR_F_END_OF_BUF RT_BIT_64(0)
186/** Default flags. */
187#define RTFUZZMUTATOR_F_DEFAULT (0)
188
189
190/**
191 * A fuzzed mutation.
192 */
193typedef struct RTFUZZMUTATION
194{
195 /** The AVL tree core. */
196 AVLU64NODECORE Core;
197 /** The list node if the mutation has the mutated
198 * data allocated. */
199 RTLISTNODE NdAlloc;
200 /** Magic identifying this structure. */
201 uint32_t u32Magic;
202 /** Reference counter. */
203 volatile uint32_t cRefs;
204 /** The fuzzer this mutation belongs to. */
205 PRTFUZZCTXINT pFuzzer;
206 /** Parent mutation (no reference is held), NULL means root or original data. */
207 PRTFUZZMUTATION pMutationParent;
208 /** Start offset where new mutations are allowed to start. */
209 uint64_t offMutStartNew;
210 /** Size of the range in bytes where mutations are allowed to happen. */
211 uint64_t cbMutNew;
212 /** Mutation level. */
213 uint32_t iLvl;
214 /** The mutator causing this mutation, NULL if original input data. */
215 PCRTFUZZMUTATOR pMutator;
216 /** Byte offset where the mutation starts. */
217 uint64_t offMutation;
218 /** Size of the generated input data in bytes after the mutation was applied. */
219 size_t cbInput;
220 /** Size of the mutation dependent data. */
221 size_t cbMutation;
222 /** Size allocated for the input. */
223 size_t cbAlloc;
224 /** Pointer to the input data if created. */
225 void *pvInput;
226 /** Flag whether the mutation is contained in the tree of the context. */
227 bool fInTree;
228 /** Flag whether the mutation input data is cached. */
229 bool fCached;
230 /** Mutation dependent data, variable in size. */
231 uint8_t abMutation[1];
232} RTFUZZMUTATION;
233
234
235/**
236 * A fuzzing input seed.
237 */
238typedef struct RTFUZZINPUTINT
239{
240 /** Magic identifying this structure. */
241 uint32_t u32Magic;
242 /** Reference counter. */
243 volatile uint32_t cRefs;
244 /** The fuzzer this input belongs to. */
245 PRTFUZZCTXINT pFuzzer;
246 /** The top mutation to work from (reference held). */
247 PRTFUZZMUTATION pMutationTop;
248 /** Fuzzer context type dependent data. */
249 union
250 {
251 /** Blob data. */
252 struct
253 {
254 /** Pointer to the input data if created. */
255 void *pvInput;
256 } Blob;
257 /** Stream state. */
258 struct
259 {
260 /** Number of bytes seen so far. */
261 size_t cbSeen;
262 } Stream;
263 } u;
264} RTFUZZINPUTINT;
265/** Pointer to the internal input state. */
266typedef RTFUZZINPUTINT *PRTFUZZINPUTINT;
267/** Pointer to an internal input state pointer. */
268typedef PRTFUZZINPUTINT *PPRTFUZZINPUTINT;
269
270
271/**
272 * The fuzzer state.
273 */
274typedef struct RTFUZZCTXINT
275{
276 /** Magic value for identification. */
277 uint32_t u32Magic;
278 /** Reference counter. */
279 volatile uint32_t cRefs;
280 /** The random number generator. */
281 RTRAND hRand;
282 /** Fuzzing context type. */
283 RTFUZZCTXTYPE enmType;
284 /** Semaphore protecting the mutations tree. */
285 RTSEMRW hSemRwMutations;
286 /** The AVL tree for indexing the mutations (keyed by counter). */
287 AVLU64TREE TreeMutations;
288 /** Number of inputs currently in the tree. */
289 volatile uint64_t cMutations;
290 /** The maximum size of one input seed to generate. */
291 size_t cbInputMax;
292 /** Behavioral flags. */
293 uint32_t fFlagsBehavioral;
294 /** Number of enabled mutators. */
295 uint32_t cMutators;
296 /** Pointer to the mutator descriptors. */
297 PRTFUZZMUTATOR paMutators;
298 /** Maximum amount of bytes of mutated inputs to cache. */
299 size_t cbMutationsAllocMax;
300 /** Current amount of bytes of cached mutated inputs. */
301 size_t cbMutationsAlloc;
302 /** List of mutators having data allocated currently. */
303 RTLISTANCHOR LstMutationsAlloc;
304 /** Critical section protecting the allocation list. */
305 RTCRITSECT CritSectAlloc;
306 /** Total number of bytes of memory currently allocated in total for this context. */
307 volatile size_t cbMemTotal;
308 /** Start offset in the input where a mutation is allowed to happen. */
309 uint64_t offMutStart;
310 /** size of the range where a mutation can happen. */
311 uint64_t cbMutRange;
312} RTFUZZCTXINT;
313
314
315/**
316 * The fuzzer state to be exported - all members are stored in little endian form.
317 */
318typedef struct RTFUZZCTXSTATE
319{
320 /** Magic value for identification. */
321 uint32_t u32Magic;
322 /** Context type. */
323 uint32_t uCtxType;
324 /** Size of the PRNG state following in bytes. */
325 uint32_t cbPrng;
326 /** Number of mutator descriptors following. */
327 uint32_t cMutators;
328 /** Number of mutation descriptors following. */
329 uint32_t cMutations;
330 /** Behavioral flags. */
331 uint32_t fFlagsBehavioral;
332 /** Maximum input size to generate. */
333 uint64_t cbInputMax;
334} RTFUZZCTXSTATE;
335/** Pointer to a fuzzing context state. */
336typedef RTFUZZCTXSTATE *PRTFUZZCTXSTATE;
337
338/** BLOB context type. */
339#define RTFUZZCTX_STATE_TYPE_BLOB UINT32_C(0)
340/** Stream context type. */
341#define RTFUZZCTX_STATE_TYPE_STREAM UINT32_C(1)
342
343
344/**
345 * The fuzzer mutation state to be exported - all members are stored in little endian form.
346 */
347typedef struct RTFUZZMUTATIONSTATE
348{
349 /** The mutation identifier. */
350 uint64_t u64Id;
351 /** The mutation identifier of the parent, 0 for no parent. */
352 uint64_t u64IdParent;
353 /** The byte offset where the mutation starts. */
354 uint64_t u64OffMutation;
355 /** Size of input data after mutation was applied. */
356 uint64_t cbInput;
357 /** Size of mutation dependent data following. */
358 uint64_t cbMutation;
359 /** The mutator ID. */
360 uint32_t u32IdMutator;
361 /** The mutation level. */
362 uint32_t iLvl;
363 /** Magic value for identification. */
364 uint32_t u32Magic;
365} RTFUZZMUTATIONSTATE;
366
367
368/**
369 * Fuzzing context memory header.
370 */
371typedef struct RTFUZZMEMHDR
372{
373 /** Size of the memory area following. */
374 size_t cb;
375#if HC_ARCH_BITS == 32
376 /** Some padding. */
377 uint32_t uPadding0;
378#elif HC_ARCH_BITS == 64
379 /** Some padding. */
380 uint64_t uPadding0;
381#else
382# error "Port me"
383#endif
384} RTFUZZMEMHDR;
385/** Pointer to a memory header. */
386typedef RTFUZZMEMHDR *PRTFUZZMEMHDR;
387
388
389/**
390 * Fuzzing context export AVL arguments.
391 */
392typedef struct RTFUZZEXPORTARGS
393{
394 /** Pointer to the export callback. */
395 PFNRTFUZZCTXEXPORT pfnExport;
396 /** Opaque user data to pass to the callback. */
397 void *pvUser;
398} RTFUZZEXPORTARGS;
399/** Pointer to the export arguments. */
400typedef RTFUZZEXPORTARGS *PRTFUZZEXPORTARGS;
401/** Pointer to the constant export arguments. */
402typedef const RTFUZZEXPORTARGS *PCRTFUZZEXPORTARGS;
403
404
405/**
406 * Integer replacing mutator additional data.
407 */
408typedef struct RTFUZZMUTATORINTEGER
409{
410 /** The integer class. */
411 uint8_t uIntClass;
412 /** Flag whether to do a byte swap. */
413 bool fByteSwap;
414 /** The index into the class specific array. */
415 uint16_t idxInt;
416} RTFUZZMUTATORINTEGER;
417/** Pointer to additional integer replacing mutator data. */
418typedef RTFUZZMUTATORINTEGER *PRTFUZZMUTATORINTEGER;
419/** Pointer to constant additional integer replacing mutator data. */
420typedef const RTFUZZMUTATORINTEGER *PCRTFUZZMUTATORINTEGER;
421
422
423/*********************************************************************************************************************************
424* Internal Functions *
425*********************************************************************************************************************************/
426static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
427 PPRTFUZZMUTATION ppMutation);
428static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
429 PPRTFUZZMUTATION ppMutation);
430static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
431 PPRTFUZZMUTATION ppMutation);
432static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
433 PPRTFUZZMUTATION ppMutation);
434static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
435 PPRTFUZZMUTATION ppMutation);
436static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
437 PPRTFUZZMUTATION ppMutation);
438static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
439 PPRTFUZZMUTATION ppMutation);
440static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
441 PPRTFUZZMUTATION ppMutation);
442
443static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
444 uint8_t *pbBuf, size_t cbBuf);
445static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
446 uint8_t *pbBuf, size_t cbBuf);
447static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
448 uint8_t *pbBuf, size_t cbBuf);
449static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
450 uint8_t *pbBuf, size_t cbBuf);
451static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
452 uint8_t *pbBuf, size_t cbBuf);
453static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
454 uint8_t *pbBuf, size_t cbBuf);
455static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
456 uint8_t *pbBuf, size_t cbBuf);
457static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
458 uint8_t *pbBuf, size_t cbBuf);
459static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
460 uint8_t *pbBuf, size_t cbBuf);
461
462static DECLCALLBACK(int) rtFuzzCtxMutatorExportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
463 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
464static DECLCALLBACK(int) rtFuzzCtxMutatorImportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
465 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
466
467static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
468 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
469static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverImport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
470 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
471
472
473/*********************************************************************************************************************************
474* Global Variables *
475*********************************************************************************************************************************/
476
477/** Signed 8bit interesting values. */
478static int8_t s_ai8Interesting[] = { INT8_MIN, INT8_MIN + 1, -1, 0, 1, INT8_MAX - 1, INT8_MAX };
479/** Unsigned 8bit interesting values. */
480static uint8_t s_au8Interesting[] = { 0, 1, UINT8_MAX - 1, UINT8_MAX };
481/** Signed 16bit interesting values. */
482static int16_t s_ai16Interesting[] = { INT16_MIN, INT16_MIN + 1, -1, 0, 1, INT16_MAX - 1, INT16_MAX };
483/** Unsigned 16bit interesting values. */
484static uint16_t s_au16Interesting[] = { 0, 1, UINT16_MAX - 1, UINT16_MAX };
485/** Signed 32bit interesting values. */
486static int32_t s_ai32Interesting[] = { INT32_MIN, INT32_MIN + 1, -1, 0, 1, INT32_MAX - 1, INT32_MAX };
487/** Unsigned 32bit interesting values. */
488static uint32_t s_au32Interesting[] = { 0, 1, UINT32_MAX - 1, UINT32_MAX };
489/** Signed 64bit interesting values. */
490static int64_t s_ai64Interesting[] = { INT64_MIN, INT64_MIN + 1, -1, 0, 1, INT64_MAX - 1, INT64_MAX };
491/** Unsigned 64bit interesting values. */
492static uint64_t s_au64Interesting[] = { 0, 1, UINT64_MAX - 1, UINT64_MAX };
493
494
495/**
496 * The special corpus mutator for the original data.
497 */
498static RTFUZZMUTATOR const g_MutatorCorpus =
499{
500 /** pszId */
501 "Corpus",
502 /** pszDesc */
503 "Special mutator, which is assigned to the initial corpus",
504 /** uMutator. */
505 RTFUZZMUTATOR_ID_CORPUS,
506 /** enmClass. */
507 RTFUZZMUTATORCLASS_BYTES,
508 /** fFlags */
509 RTFUZZMUTATOR_F_DEFAULT,
510 /** pfnPrep */
511 NULL,
512 /** pfnExec */
513 rtFuzzCtxMutatorCorpusExec,
514 /** pfnExport */
515 rtFuzzCtxMutatorExportDefault,
516 /** pfnImport */
517 rtFuzzCtxMutatorImportDefault
518};
519
520/**
521 * Array of all available mutators.
522 */
523static RTFUZZMUTATOR const g_aMutators[] =
524{
525 /* pszId pszDesc uMutator enmClass fFlags pfnPrep pfnExec pfnExport pfnImport */
526 { "BitFlip", "Flips a single bit in the input", 0, RTFUZZMUTATORCLASS_BITS, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorBitFlipPrep, rtFuzzCtxMutatorBitFlipExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
527 { "ByteReplace", "Replaces a single byte in the input", 1, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteReplacePrep, rtFuzzCtxMutatorByteReplaceExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
528 { "ByteInsert", "Inserts a single byte sequence into the input", 2, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteInsertPrep, rtFuzzCtxMutatorByteInsertExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
529 { "ByteSeqIns", "Inserts a byte sequence in the input", 3, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
530 { "ByteSeqApp", "Appends a byte sequence to the input", 4, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
531 { "ByteDelete", "Deletes a single byte sequence from the input", 5, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteDeletePrep, rtFuzzCtxMutatorByteDeleteExec, NULL, NULL },
532 { "ByteSeqDel", "Deletes a byte sequence from the input", 6, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceDeletePrep, rtFuzzCtxMutatorByteSequenceDeleteExec, NULL, NULL },
533 { "IntReplace", "Replaces a possible integer with an interesting one", 7, RTFUZZMUTATORCLASS_INTEGERS, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorIntegerReplacePrep, rtFuzzCtxMutatorIntegerReplaceExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
534 { "MutCrossover", "Creates a crossover of two other mutations", 8, RTFUZZMUTATORCLASS_MUTATORS, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorCrossoverPrep, rtFuzzCtxMutatorCrossoverExec, rtFuzzCtxMutatorCrossoverExport, rtFuzzCtxMutatorCrossoverImport }
535};
536
537
538/**
539 * Allocates the given number of bytes.
540 *
541 * @returns Pointer to the allocated memory
542 * @param pThis The fuzzer context instance.
543 * @param cb How much to allocate.
544 */
545static void *rtFuzzCtxMemoryAlloc(PRTFUZZCTXINT pThis, size_t cb)
546{
547 AssertReturn(cb > 0, NULL);
548
549 PRTFUZZMEMHDR pMemHdr = (PRTFUZZMEMHDR)RTMemAllocZ(cb + sizeof(RTFUZZMEMHDR));
550 if (RT_LIKELY(pMemHdr))
551 {
552 pMemHdr->cb = cb;
553 size_t cbIgn = ASMAtomicAddZ(&pThis->cbMemTotal, cb + sizeof(RTFUZZMEMHDR)); RT_NOREF(cbIgn);
554 return pMemHdr + 1;
555 }
556
557 return NULL;
558}
559
560
561/**
562 * Frees the given memory.
563 *
564 * @returns nothing.
565 * @param pThis The fuzzer context instance.
566 * @param pv Pointer to the memory area to free.
567 */
568static void rtFuzzCtxMemoryFree(PRTFUZZCTXINT pThis, void *pv)
569{
570 AssertReturnVoid(pv != NULL);
571 PRTFUZZMEMHDR pMemHdr = ((PRTFUZZMEMHDR)pv) - 1;
572
573 size_t cbIgn = ASMAtomicSubZ(&pThis->cbMemTotal, pMemHdr->cb + sizeof(RTFUZZMEMHDR)); RT_NOREF(cbIgn);
574 RTMemFree(pMemHdr);
575}
576
577
578/**
579 * Frees the cached inputs until the given amount is free.
580 *
581 * @returns Whether the amount of memory is free.
582 * @param pThis The fuzzer context instance.
583 * @param cb How many bytes to reclaim
584 */
585static bool rtFuzzCtxMutationAllocReclaim(PRTFUZZCTXINT pThis, size_t cb)
586{
587 while ( !RTListIsEmpty(&pThis->LstMutationsAlloc)
588 && pThis->cbMutationsAlloc + cb > pThis->cbMutationsAllocMax)
589 {
590 PRTFUZZMUTATION pMutation = RTListGetLast(&pThis->LstMutationsAlloc, RTFUZZMUTATION, NdAlloc);
591 AssertPtr(pMutation);
592 AssertPtr(pMutation->pvInput);
593
594 rtFuzzCtxMemoryFree(pThis, pMutation->pvInput);
595 pThis->cbMutationsAlloc -= pMutation->cbAlloc;
596 pMutation->pvInput = NULL;
597 pMutation->cbAlloc = 0;
598 pMutation->fCached = false;
599 RTListNodeRemove(&pMutation->NdAlloc);
600 }
601
602 return pThis->cbMutationsAlloc + cb <= pThis->cbMutationsAllocMax;
603}
604
605
606/**
607 * Updates the cache status of the given mutation.
608 *
609 * @returns nothing.
610 * @param pThis The fuzzer context instance.
611 * @param pMutation The mutation to update.
612 */
613static void rtFuzzCtxMutationMaybeEnterCache(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation)
614{
615 RTCritSectEnter(&pThis->CritSectAlloc);
616
617 /* Initial corpus mutations are not freed. */
618 if ( pMutation->pvInput
619 && pMutation->pMutator != &g_MutatorCorpus)
620 {
621 Assert(!pMutation->fCached);
622
623 if (rtFuzzCtxMutationAllocReclaim(pThis, pMutation->cbAlloc))
624 {
625 RTListPrepend(&pThis->LstMutationsAlloc, &pMutation->NdAlloc);
626 pThis->cbMutationsAlloc += pMutation->cbAlloc;
627 pMutation->fCached = true;
628 }
629 else
630 {
631 rtFuzzCtxMemoryFree(pThis, pMutation->pvInput);
632 pMutation->pvInput = NULL;
633 pMutation->cbAlloc = 0;
634 pMutation->fCached = false;
635 }
636 }
637 RTCritSectLeave(&pThis->CritSectAlloc);
638}
639
640
641/**
642 * Removes a cached mutation from the cache.
643 *
644 * @returns nothing.
645 * @param pThis The fuzzer context instance.
646 * @param pMutation The mutation to remove.
647 */
648static void rtFuzzCtxMutationCacheRemove(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation)
649{
650 RTCritSectEnter(&pThis->CritSectAlloc);
651 if (pMutation->fCached)
652 {
653 RTListNodeRemove(&pMutation->NdAlloc);
654 pThis->cbMutationsAlloc -= pMutation->cbAlloc;
655 pMutation->fCached = false;
656 }
657 RTCritSectLeave(&pThis->CritSectAlloc);
658}
659
660
661/**
662 * Destroys the given mutation.
663 *
664 * @returns nothing.
665 * @param pMutation The mutation to destroy.
666 */
667static void rtFuzzMutationDestroy(PRTFUZZMUTATION pMutation)
668{
669 if (pMutation->pvInput)
670 {
671 rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation->pvInput);
672 if (pMutation->fCached)
673 {
674 RTCritSectEnter(&pMutation->pFuzzer->CritSectAlloc);
675 RTListNodeRemove(&pMutation->NdAlloc);
676 pMutation->pFuzzer->cbMutationsAlloc -= pMutation->cbAlloc;
677 RTCritSectLeave(&pMutation->pFuzzer->CritSectAlloc);
678 }
679 pMutation->pvInput = NULL;
680 pMutation->cbAlloc = 0;
681 pMutation->fCached = false;
682 }
683 rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation);
684}
685
686
687/**
688 * Retains an external reference to the given mutation.
689 *
690 * @returns New reference count on success.
691 * @param pMutation The mutation to retain.
692 */
693static uint32_t rtFuzzMutationRetain(PRTFUZZMUTATION pMutation)
694{
695 uint32_t cRefs = ASMAtomicIncU32(&pMutation->cRefs);
696 AssertMsg( ( cRefs > 1
697 || pMutation->fInTree)
698 && cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
699
700 if (cRefs == 1)
701 rtFuzzCtxMutationCacheRemove(pMutation->pFuzzer, pMutation);
702 return cRefs;
703}
704
705
706/**
707 * Releases an external reference from the given mutation.
708 *
709 * @returns New reference count on success.
710 * @param pMutation The mutation to retain.
711 */
712static uint32_t rtFuzzMutationRelease(PRTFUZZMUTATION pMutation)
713{
714 uint32_t cRefs = ASMAtomicDecU32(&pMutation->cRefs);
715 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pMutation));
716
717 if (cRefs == 0)
718 {
719 if (!pMutation->fInTree)
720 rtFuzzMutationDestroy(pMutation);
721 else
722 rtFuzzCtxMutationMaybeEnterCache(pMutation->pFuzzer, pMutation);
723 }
724
725 return cRefs;
726}
727
728
729/**
730 * Adds the given mutation to the corpus of the given fuzzer context.
731 *
732 * @returns IPRT status code.
733 * @param pThis The fuzzer context instance.
734 * @param pMutation The mutation to add.
735 */
736static int rtFuzzCtxMutationAdd(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation)
737{
738 int rc = VINF_SUCCESS;
739
740 pMutation->Core.Key = ASMAtomicIncU64(&pThis->cMutations);
741 rc = RTSemRWRequestWrite(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
742 AssertRC(rc); RT_NOREF(rc);
743 bool fIns = RTAvlU64Insert(&pThis->TreeMutations, &pMutation->Core);
744 Assert(fIns); RT_NOREF(fIns);
745 rc = RTSemRWReleaseWrite(pThis->hSemRwMutations);
746 AssertRC(rc); RT_NOREF(rc);
747
748 pMutation->fInTree = true;
749 return rc;
750}
751
752
753/**
754 * Locates the mutation with the given key.
755 *
756 * @returns Pointer to the mutation if found or NULL otherwise.
757 * @param pThis The fuzzer context instance.
758 * @param uKey The key to locate.
759 */
760static PRTFUZZMUTATION rtFuzzCtxMutationLocate(PRTFUZZCTXINT pThis, uint64_t uKey)
761{
762 int rc = RTSemRWRequestRead(pThis->hSemRwMutations, RT_INDEFINITE_WAIT);
763 AssertRC(rc); RT_NOREF(rc);
764
765 /*
766 * Using best fit getter here as there might be a racing mutation insertion and the mutation counter has increased
767 * already but the mutation is not yet in the tree.
768 */
769 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)RTAvlU64GetBestFit(&pThis->TreeMutations, uKey, false /*fAbove*/);
770 if (RT_LIKELY(pMutation))
771 rtFuzzMutationRetain(pMutation);
772
773 rc = RTSemRWReleaseRead(pThis->hSemRwMutations);
774 AssertRC(rc); RT_NOREF(rc);
775
776 return pMutation;
777}
778
779
780/**
781 * Returns a random mutation from the corpus of the given fuzzer context.
782 *
783 * @returns Pointer to a randomly picked mutation (reference count is increased).
784 * @param pThis The fuzzer context instance.
785 */
786static PRTFUZZMUTATION rtFuzzCtxMutationPickRnd(PRTFUZZCTXINT pThis)
787{
788 uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 1, ASMAtomicReadU64(&pThis->cMutations));
789 return rtFuzzCtxMutationLocate(pThis, idxMutation);
790}
791
792
793/**
794 * Creates a new mutation capable of holding the additional number of bytes - extended version.
795 *
796 * @returns Pointer to the newly created mutation or NULL if out of memory.
797 * @param pThis The fuzzer context instance.
798 * @param offMutation The starting offset for the mutation.
799 * @param pMutationParent The parent mutation, can be NULL.
800 * @param offMuStartNew Offset where descendants of the created mutation can start to mutate.
801 * @param cbMutNew Range in bytes where descendants of the created mutation can mutate.c
802 * @param cbAdditional Additional number of bytes to allocate after the core structure.
803 * @param ppvMutation Where to store the pointer to the mutation dependent data on success.
804 */
805static PRTFUZZMUTATION rtFuzzMutationCreateEx(PRTFUZZCTXINT pThis, uint64_t offMutation, PRTFUZZMUTATION pMutationParent,
806 uint64_t offMutStartNew, uint64_t cbMutNew, size_t cbAdditional, void **ppvMutation)
807{
808 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)rtFuzzCtxMemoryAlloc(pThis, sizeof(RTFUZZMUTATION) + cbAdditional);
809 if (RT_LIKELY(pMutation))
810 {
811 pMutation->u32Magic = 0; /** @todo */
812 pMutation->pFuzzer = pThis;
813 pMutation->cRefs = 1;
814 pMutation->iLvl = 0;
815 pMutation->offMutation = offMutation;
816 pMutation->pMutationParent = pMutationParent;
817 pMutation->offMutStartNew = offMutStartNew;
818 pMutation->cbMutNew = cbMutNew;
819 pMutation->cbMutation = cbAdditional;
820 pMutation->fInTree = false;
821 pMutation->fCached = false;
822 pMutation->pvInput = NULL;
823 pMutation->cbInput = 0;
824 pMutation->cbAlloc = 0;
825
826 if (pMutationParent)
827 pMutation->iLvl = pMutationParent->iLvl + 1;
828 if (ppvMutation)
829 *ppvMutation = &pMutation->abMutation[0];
830 }
831
832 return pMutation;
833}
834
835
836/**
837 * Creates a new mutation capable of holding the additional number of bytes.
838 *
839 * @returns Pointer to the newly created mutation or NULL if out of memory.
840 * @param pThis The fuzzer context instance.
841 * @param offMutation The starting offset for the mutation.
842 * @param pMutationParent The parent mutation, can be NULL.
843 * @param cbAdditional Additional number of bytes to allocate after the core structure.
844 * @param ppvMutation Where to store the pointer to the mutation dependent data on success.
845 */
846DECLINLINE(PRTFUZZMUTATION) rtFuzzMutationCreate(PRTFUZZCTXINT pThis, uint64_t offMutation, PRTFUZZMUTATION pMutationParent,
847 size_t cbAdditional, void **ppvMutation)
848{
849 uint64_t offMutNew = pMutationParent ? pMutationParent->offMutStartNew : pThis->offMutStart;
850 uint64_t cbMutNew = pMutationParent ? pMutationParent->cbMutNew : pThis->cbMutRange;
851
852 return rtFuzzMutationCreateEx(pThis, offMutation, pMutationParent, offMutNew, cbMutNew, cbAdditional, ppvMutation);
853}
854
855
856/**
857 * Destroys the given fuzzer context freeing all allocated resources.
858 *
859 * @returns nothing.
860 * @param pThis The fuzzer context instance.
861 */
862static void rtFuzzCtxDestroy(PRTFUZZCTXINT pThis)
863{
864 RT_NOREF(pThis);
865}
866
867
868/**
869 * Creates the final input data applying all accumulated mutations.
870 *
871 * @returns IPRT status code.
872 * @param pMutation The mutation to finalize.
873 */
874static int rtFuzzMutationDataFinalize(PRTFUZZMUTATION pMutation)
875{
876 if (pMutation->pvInput)
877 return VINF_SUCCESS;
878
879 /* Traverse the mutations top to bottom and insert into the array. */
880 int rc = VINF_SUCCESS;
881 uint32_t idx = pMutation->iLvl + 1;
882 PRTFUZZMUTATION *papMutations = (PRTFUZZMUTATION *)RTMemTmpAlloc(idx * sizeof(PCRTFUZZMUTATION));
883 if (RT_LIKELY(papMutations))
884 {
885 PRTFUZZMUTATION pMutationCur = pMutation;
886 size_t cbAlloc = 0;
887
888 /*
889 * As soon as a mutation with allocated input data is encountered the insertion is
890 * stopped as it contains all necessary mutated inputs we can start from.
891 */
892 while (idx > 0)
893 {
894 rtFuzzMutationRetain(pMutationCur);
895 papMutations[idx - 1] = pMutationCur;
896 cbAlloc = RT_MAX(cbAlloc, pMutationCur->cbInput);
897 if (pMutationCur->pvInput)
898 {
899 idx--;
900 break;
901 }
902 pMutationCur = pMutationCur->pMutationParent;
903 idx--;
904 }
905
906 pMutation->cbAlloc = cbAlloc;
907 uint8_t *pbBuf = (uint8_t *)rtFuzzCtxMemoryAlloc(pMutation->pFuzzer, cbAlloc);
908 if (RT_LIKELY(pbBuf))
909 {
910 pMutation->pvInput = pbBuf;
911
912 /* Copy the initial input data. */
913 size_t cbInputNow = papMutations[idx]->cbInput;
914 memcpy(pbBuf, papMutations[idx]->pvInput, cbInputNow);
915 rtFuzzMutationRelease(papMutations[idx]);
916
917 for (uint32_t i = idx + 1; i < pMutation->iLvl + 1; i++)
918 {
919 PRTFUZZMUTATION pCur = papMutations[i];
920 pCur->pMutator->pfnExec(pCur->pFuzzer, pCur, (void *)&pCur->abMutation[0],
921 pbBuf + pCur->offMutation,
922 cbInputNow - pCur->offMutation);
923
924 cbInputNow = pCur->cbInput;
925 rtFuzzMutationRelease(pCur);
926 }
927
928 Assert(cbInputNow == pMutation->cbInput);
929 }
930 else
931 rc = VERR_NO_MEMORY;
932
933 RTMemTmpFree(papMutations);
934 }
935 else
936 rc = VERR_NO_MEMORY;
937
938 return rc;
939}
940
941
942/**
943 * Default mutator export callback (just writing the raw data).
944 */
945static DECLCALLBACK(int) rtFuzzCtxMutatorExportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
946 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser)
947{
948 return pfnExport(pThis, pvMutation, pMutation->cbMutation, pvUser);
949}
950
951
952/**
953 * Default mutator import callback (just reading the raw data).
954 */
955static DECLCALLBACK(int) rtFuzzCtxMutatorImportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
956 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser)
957{
958 return pfnImport(pThis, pvMutation, pMutation->cbMutation, NULL, pvUser);
959}
960
961
962static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
963 uint8_t *pbBuf, size_t cbBuf)
964{
965 RT_NOREF(pThis, cbBuf, pvMutation);
966 memcpy(pbBuf, pvMutation, pMutation->cbInput);
967 return VINF_SUCCESS;
968}
969
970
971/**
972 * Mutator callback - flips a single bit in the input.
973 */
974static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
975 PPRTFUZZMUTATION ppMutation)
976{
977 int rc = VINF_SUCCESS;
978 uint8_t *pidxBitFlip = 0;
979 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pidxBitFlip), (void **)&pidxBitFlip);
980 if (RT_LIKELY(pMutation))
981 {
982 pMutation->cbInput = pMutationParent->cbInput; /* Bit flips don't change the input size. */
983 *pidxBitFlip = (uint8_t)RTRandAdvU32Ex(pThis->hRand, 0, sizeof(uint8_t) * 8 - 1);
984 *ppMutation = pMutation;
985 }
986 else
987 rc = VERR_NO_MEMORY;
988
989 return rc;
990}
991
992
993static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
994 uint8_t *pbBuf, size_t cbBuf)
995{
996 RT_NOREF(pThis, cbBuf, pMutation);
997 uint8_t idxBitFlip = *(uint8_t *)pvMutation;
998 ASMBitToggle(pbBuf, idxBitFlip);
999 return VINF_SUCCESS;
1000}
1001
1002
1003/**
1004 * Mutator callback - replaces a single byte in the input.
1005 */
1006static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
1007 PPRTFUZZMUTATION ppMutation)
1008{
1009 int rc = VINF_SUCCESS;
1010 uint8_t *pbReplace = 0;
1011 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pbReplace), (void **)&pbReplace);
1012 if (RT_LIKELY(pMutation))
1013 {
1014 pMutation->cbInput = pMutationParent->cbInput; /* Byte replacements don't change the input size. */
1015 RTRandAdvBytes(pThis->hRand, pbReplace, 1); /** @todo Filter out same values. */
1016 *ppMutation = pMutation;
1017 }
1018 else
1019 rc = VERR_NO_MEMORY;
1020
1021 return rc;
1022}
1023
1024
1025static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1026 uint8_t *pbBuf, size_t cbBuf)
1027{
1028 RT_NOREF(pThis, cbBuf, pMutation);
1029 uint8_t bReplace = *(uint8_t *)pvMutation;
1030 *pbBuf = bReplace;
1031 return VINF_SUCCESS;
1032}
1033
1034
1035/**
1036 * Mutator callback - inserts a single byte into the input.
1037 */
1038static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
1039 PPRTFUZZMUTATION ppMutation)
1040{
1041 int rc = VINF_SUCCESS;
1042 uint8_t *pbInsert = 0;
1043 if (pMutationParent->cbInput < pThis->cbInputMax)
1044 {
1045 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 1 /*cbAdditional*/, (void **)&pbInsert);
1046 if (RT_LIKELY(pMutation))
1047 {
1048 pMutation->cbInput = pMutationParent->cbInput + 1;
1049 RTRandAdvBytes(pThis->hRand, pbInsert, 1);
1050 *ppMutation = pMutation;
1051 }
1052 else
1053 rc = VERR_NO_MEMORY;
1054 }
1055
1056 return rc;
1057}
1058
1059
1060static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1061 uint8_t *pbBuf, size_t cbBuf)
1062{
1063 RT_NOREF(pThis, pMutation, pvMutation);
1064
1065 /* Just move the residual data one byte to the back. */
1066 memmove(pbBuf + 1, pbBuf, cbBuf);
1067 *pbBuf = *(uint8_t *)pvMutation;
1068 return VINF_SUCCESS;
1069}
1070
1071
1072/**
1073 * Mutator callback - inserts a byte sequence into the input.
1074 */
1075static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
1076 PPRTFUZZMUTATION ppMutation)
1077{
1078 int rc = VINF_SUCCESS;
1079 if (pMutationParent->cbInput < pThis->cbInputMax)
1080 {
1081 size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, pMutationParent->cbInput + 1, pThis->cbInputMax);
1082 size_t cbInsert = cbInputMutated - pMutationParent->cbInput;
1083 uint8_t *pbAdd = NULL;
1084
1085 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, cbInsert, (void **)&pbAdd);
1086 if (RT_LIKELY(pMutation))
1087 {
1088 pMutation->cbInput = cbInputMutated;
1089 RTRandAdvBytes(pThis->hRand, pbAdd, cbInsert);
1090 *ppMutation = pMutation;
1091 }
1092 else
1093 rc = VERR_NO_MEMORY;
1094 }
1095
1096 return rc;
1097}
1098
1099
1100static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1101 uint8_t *pbBuf, size_t cbBuf)
1102{
1103 RT_NOREF(pThis);
1104 size_t cbInsert = pMutation->cbInput - pMutation->pMutationParent->cbInput;
1105
1106 /* Move any remaining data to the end. */
1107 if (cbBuf)
1108 memmove(pbBuf + cbInsert, pbBuf, cbBuf);
1109
1110 memcpy(pbBuf, pvMutation, cbInsert);
1111 return VINF_SUCCESS;
1112}
1113
1114
1115/**
1116 * Mutator callback - deletes a single byte in the input.
1117 */
1118static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
1119 PPRTFUZZMUTATION ppMutation)
1120{
1121 int rc = VINF_SUCCESS;
1122 if (pMutationParent->cbInput - offStart >= 1)
1123 {
1124 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/, NULL);
1125 if (RT_LIKELY(pMutation))
1126 {
1127 pMutation->cbInput = pMutationParent->cbInput - 1;
1128 *ppMutation = pMutation;
1129 }
1130 else
1131 rc = VERR_NO_MEMORY;
1132 }
1133
1134 return rc;
1135}
1136
1137
1138static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1139 uint8_t *pbBuf, size_t cbBuf)
1140{
1141 RT_NOREF(pThis, pMutation, pvMutation);
1142
1143 /* Just move the residual data to the front. */
1144 memmove(pbBuf, pbBuf + 1, cbBuf - 1);
1145 return VINF_SUCCESS;
1146}
1147
1148
1149/**
1150 * Mutator callback - deletes a byte sequence in the input.
1151 */
1152static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
1153 PPRTFUZZMUTATION ppMutation)
1154{
1155 int rc = VINF_SUCCESS;
1156 if ( pMutationParent->cbInput > offStart
1157 && pMutationParent->cbInput > 1)
1158 {
1159 size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, offStart, pMutationParent->cbInput - 1);
1160
1161 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/, NULL);
1162 if (RT_LIKELY(pMutation))
1163 {
1164 pMutation->cbInput = cbInputMutated;
1165 *ppMutation = pMutation;
1166 }
1167 else
1168 rc = VERR_NO_MEMORY;
1169 }
1170
1171 return rc;
1172}
1173
1174
1175static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1176 uint8_t *pbBuf, size_t cbBuf)
1177{
1178 RT_NOREF(pThis, pvMutation);
1179 Assert(pMutation->pMutationParent->cbInput > pMutation->cbInput);
1180 size_t cbDel = pMutation->pMutationParent->cbInput - pMutation->cbInput;
1181
1182 /* Just move the residual data to the front. */
1183 memmove(pbBuf, pbBuf + cbDel, cbBuf - cbDel);
1184 return VINF_SUCCESS;
1185}
1186
1187
1188/**
1189 * Mutator callback - replaces a possible integer with something interesting.
1190 */
1191static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
1192 PPRTFUZZMUTATION ppMutation)
1193{
1194 int rc = VINF_SUCCESS;
1195 PRTFUZZMUTATORINTEGER pMutInt = NULL;
1196 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pMutInt), (void **)&pMutInt);
1197 if (RT_LIKELY(pMutation))
1198 {
1199 size_t cbLeft = pMutationParent->cbInput - offStart;
1200 uint32_t uClassMax = 0;
1201
1202 switch (cbLeft)
1203 {
1204 case 1:
1205 uClassMax = 1;
1206 break;
1207 case 2:
1208 case 3:
1209 uClassMax = 3;
1210 break;
1211 case 4:
1212 case 5:
1213 case 6:
1214 case 7:
1215 uClassMax = 5;
1216 break;
1217 default:
1218 uClassMax = 7;
1219 break;
1220 }
1221
1222 pMutInt->uIntClass = (uint8_t)RTRandAdvU32Ex(pThis->hRand, 0, uClassMax);
1223 pMutInt->fByteSwap = RT_BOOL(RTRandAdvU32Ex(pThis->hRand, 0, 1));
1224
1225 switch (pMutInt->uIntClass)
1226 {
1227 case 0:
1228 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai8Interesting) - 1);
1229 break;
1230 case 1:
1231 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au8Interesting) - 1);
1232 break;
1233 case 2:
1234 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai16Interesting) - 1);
1235 break;
1236 case 3:
1237 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au16Interesting) - 1);
1238 break;
1239 case 4:
1240 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai32Interesting) - 1);
1241 break;
1242 case 5:
1243 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au32Interesting) - 1);
1244 break;
1245 case 6:
1246 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai64Interesting) - 1);
1247 break;
1248 case 7:
1249 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au64Interesting) - 1);
1250 break;
1251 default:
1252 AssertReleaseFailed();
1253 }
1254
1255 pMutation->cbInput = pMutationParent->cbInput;
1256 *ppMutation = pMutation;
1257 }
1258 else
1259 rc = VERR_NO_MEMORY;
1260
1261 return rc;
1262}
1263
1264
1265static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1266 uint8_t *pbBuf, size_t cbBuf)
1267{
1268 RT_NOREF(pThis, pMutation, cbBuf);
1269 union
1270 {
1271 int8_t i8;
1272 uint8_t u8;
1273 int16_t i16;
1274 uint16_t u16;
1275 int32_t i32;
1276 uint32_t u32;
1277 int64_t i64;
1278 uint64_t u64;
1279 } Int;
1280 PCRTFUZZMUTATORINTEGER pMutInt = (PCRTFUZZMUTATORINTEGER)pvMutation;
1281 size_t cb = 0;
1282
1283 switch (pMutInt->uIntClass)
1284 {
1285 case 0:
1286 Int.i8 = s_ai8Interesting[pMutInt->idxInt];
1287 cb = 1;
1288 break;
1289 case 1:
1290 Int.u8 = s_au8Interesting[pMutInt->idxInt];
1291 cb = 1;
1292 break;
1293 case 2:
1294 Int.i16 = s_ai16Interesting[pMutInt->idxInt];
1295 cb = 2;
1296 if (pMutInt->fByteSwap)
1297 Int.u16 = RT_BSWAP_U16(Int.u16);
1298 break;
1299 case 3:
1300 Int.u16 = s_au16Interesting[pMutInt->idxInt];
1301 cb = 2;
1302 if (pMutInt->fByteSwap)
1303 Int.u16 = RT_BSWAP_U16(Int.u16);
1304 break;
1305 case 4:
1306 Int.i32 = s_ai32Interesting[pMutInt->idxInt];
1307 cb = 4;
1308 if (pMutInt->fByteSwap)
1309 Int.u32 = RT_BSWAP_U32(Int.u32);
1310 break;
1311 case 5:
1312 Int.u32 = s_au32Interesting[pMutInt->idxInt];
1313 cb = 4;
1314 if (pMutInt->fByteSwap)
1315 Int.u32 = RT_BSWAP_U32(Int.u32);
1316 break;
1317 case 6:
1318 Int.i64 = s_ai64Interesting[pMutInt->idxInt];
1319 cb = 8;
1320 if (pMutInt->fByteSwap)
1321 Int.u64 = RT_BSWAP_U64(Int.u64);
1322 break;
1323 case 7:
1324 Int.u64 = s_au64Interesting[pMutInt->idxInt];
1325 cb = 8;
1326 if (pMutInt->fByteSwap)
1327 Int.u64 = RT_BSWAP_U64(Int.u64);
1328 break;
1329 default:
1330 AssertReleaseFailed();
1331 }
1332
1333 memcpy(pbBuf, &Int, cb);
1334 return VINF_SUCCESS;
1335}
1336
1337
1338/**
1339 * Mutator callback - crosses over two mutations at the given point.
1340 */
1341static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
1342 PPRTFUZZMUTATION ppMutation)
1343{
1344 int rc = VINF_SUCCESS;
1345
1346 if (pThis->cMutations > 1)
1347 {
1348 uint64_t *pidxMutCrossover = NULL;
1349 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pidxMutCrossover), (void **)&pidxMutCrossover);
1350 if (RT_LIKELY(pMutation))
1351 {
1352 uint32_t cTries = 10;
1353 PRTFUZZMUTATION pMutCrossover = NULL;
1354 /*
1355 * Pick a random mutation to crossover with (making sure it is not the current one
1356 * or the crossover point is beyond the end of input).
1357 */
1358 do
1359 {
1360 if (pMutCrossover)
1361 rtFuzzMutationRelease(pMutCrossover);
1362 pMutCrossover = rtFuzzCtxMutationPickRnd(pThis);
1363 cTries--;
1364 } while ( ( pMutCrossover == pMutationParent
1365 || offStart >= pMutCrossover->cbInput)
1366 && cTries > 0);
1367
1368 if (cTries)
1369 {
1370 pMutation->cbInput = pMutCrossover->cbInput;
1371 *pidxMutCrossover = pMutCrossover->Core.Key;
1372 *ppMutation = pMutation;
1373 }
1374 else
1375 rtFuzzMutationDestroy(pMutation);
1376
1377 rtFuzzMutationRelease(pMutCrossover);
1378 }
1379 else
1380 rc = VERR_NO_MEMORY;
1381 }
1382
1383 return rc;
1384}
1385
1386
1387static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1388 uint8_t *pbBuf, size_t cbBuf)
1389{
1390 RT_NOREF(cbBuf);
1391 uint64_t idxMutCrossover = *(uint64_t *)pvMutation;
1392
1393 PRTFUZZMUTATION pMutCrossover = rtFuzzCtxMutationLocate(pThis, idxMutCrossover);
1394 int rc = rtFuzzMutationDataFinalize(pMutCrossover);
1395 if (RT_SUCCESS(rc))
1396 {
1397 memcpy(pbBuf, (uint8_t *)pMutCrossover->pvInput + pMutation->offMutation,
1398 pMutCrossover->cbInput - pMutation->offMutation);
1399 rtFuzzMutationRelease(pMutCrossover);
1400 }
1401
1402 return rc;
1403}
1404
1405
1406static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
1407 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser)
1408{
1409 RT_NOREF(pMutation);
1410
1411 uint64_t idxMutCrossover = *(uint64_t *)pvMutation;
1412 idxMutCrossover = RT_H2LE_U64(idxMutCrossover);
1413 return pfnExport(pThis, &idxMutCrossover, sizeof(idxMutCrossover), pvUser);
1414}
1415
1416
1417static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverImport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation,
1418 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser)
1419{
1420 RT_NOREF(pMutation);
1421
1422 uint64_t uKey = 0;
1423 int rc = pfnImport(pThis, &uKey, sizeof(uKey), NULL, pvUser);
1424 if (RT_SUCCESS(rc))
1425 {
1426 uKey = RT_LE2H_U64(uKey);
1427 *(uint64_t *)pvMutation = uKey;
1428 }
1429
1430 return rc;
1431}
1432
1433
1434/**
1435 * Creates an empty fuzzing context.
1436 *
1437 * @returns IPRT status code.
1438 * @param ppThis Where to store the pointer to the internal fuzzing context instance on success.
1439 * @param enmType Fuzzing context type.
1440 */
1441static int rtFuzzCtxCreateEmpty(PRTFUZZCTXINT *ppThis, RTFUZZCTXTYPE enmType)
1442{
1443 int rc;
1444 PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis));
1445 if (RT_LIKELY(pThis))
1446 {
1447 pThis->u32Magic = RTFUZZCTX_MAGIC;
1448 pThis->cRefs = 1;
1449 pThis->enmType = enmType;
1450 pThis->TreeMutations = NULL;
1451 pThis->cbInputMax = UINT32_MAX;
1452 pThis->cMutations = 0;
1453 pThis->fFlagsBehavioral = 0;
1454 pThis->cbMutationsAllocMax = _1G;
1455 pThis->cbMemTotal = 0;
1456 pThis->offMutStart = 0;
1457 pThis->cbMutRange = UINT64_MAX;
1458 RTListInit(&pThis->LstMutationsAlloc);
1459
1460 /* Copy the default mutator descriptors over. */
1461 pThis->paMutators = (PRTFUZZMUTATOR)RTMemAllocZ(RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR));
1462 if (RT_LIKELY(pThis->paMutators))
1463 {
1464 pThis->cMutators = RT_ELEMENTS(g_aMutators);
1465 memcpy(&pThis->paMutators[0], &g_aMutators[0], RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR));
1466
1467 rc = RTSemRWCreate(&pThis->hSemRwMutations);
1468 if (RT_SUCCESS(rc))
1469 {
1470 rc = RTCritSectInit(&pThis->CritSectAlloc);
1471 if (RT_SUCCESS(rc))
1472 {
1473 rc = RTRandAdvCreateParkMiller(&pThis->hRand);
1474 if (RT_SUCCESS(rc))
1475 {
1476 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS());
1477 *ppThis = pThis;
1478 return VINF_SUCCESS;
1479 }
1480
1481 RTCritSectDelete(&pThis->CritSectAlloc);
1482 }
1483
1484 RTSemRWDestroy(pThis->hSemRwMutations);
1485 }
1486 }
1487 else
1488 rc = VERR_NO_MEMORY;
1489
1490 RTMemFree(pThis);
1491 }
1492 else
1493 rc = VERR_NO_MEMORY;
1494
1495 return rc;
1496}
1497
1498
1499/**
1500 * Destroys the given fuzzing input.
1501 *
1502 * @returns nothing.
1503 * @param pThis The fuzzing input to destroy.
1504 */
1505static void rtFuzzInputDestroy(PRTFUZZINPUTINT pThis)
1506{
1507 PRTFUZZCTXINT pFuzzer = pThis->pFuzzer;
1508
1509 rtFuzzMutationRelease(pThis->pMutationTop);
1510 rtFuzzCtxMemoryFree(pFuzzer, pThis);
1511 RTFuzzCtxRelease(pFuzzer);
1512}
1513
1514
1515RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx, RTFUZZCTXTYPE enmType)
1516{
1517 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
1518
1519 return rtFuzzCtxCreateEmpty(phFuzzCtx, enmType);
1520}
1521
1522
1523RTDECL(int) RTFuzzCtxCreateFromState(PRTFUZZCTX phFuzzCtx, PFNRTFUZZCTXIMPORT pfnImport, void *pvUser)
1524{
1525 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
1526 AssertPtrReturn(pfnImport, VERR_INVALID_POINTER);
1527
1528#if 0
1529 int rc = VINF_SUCCESS;
1530 if (cbState >= sizeof(RTFUZZCTXSTATE))
1531 {
1532 RTFUZZCTXSTATE StateImport;
1533
1534 memcpy(&StateImport, pvState, sizeof(RTFUZZCTXSTATE));
1535 if ( RT_LE2H_U32(StateImport.u32Magic) == RTFUZZCTX_MAGIC
1536 && RT_LE2H_U32(StateImport.cbPrng) <= cbState - sizeof(RTFUZZCTXSTATE))
1537 {
1538 PRTFUZZCTXINT pThis = rtFuzzCtxCreateEmpty();
1539 if (RT_LIKELY(pThis))
1540 {
1541 pThis->cbInputMax = (size_t)RT_LE2H_U64(StateImport.cbInputMax);
1542 pThis->fFlagsBehavioral = RT_LE2H_U32(StateImport.fFlagsBehavioral);
1543
1544 uint8_t *pbState = (uint8_t *)pvState;
1545 uint32_t cInputs = RT_LE2H_U32(StateImport.cInputs);
1546 rc = RTRandAdvRestoreState(pThis->hRand, (const char *)&pbState[sizeof(RTFUZZCTXSTATE)]);
1547 if (RT_SUCCESS(rc))
1548 {
1549 /* Go through the inputs and add them. */
1550 pbState += sizeof(RTFUZZCTXSTATE) + RT_LE2H_U32(StateImport.cbPrng);
1551 cbState -= sizeof(RTFUZZCTXSTATE) + RT_LE2H_U32(StateImport.cbPrng);
1552
1553 uint32_t idx = 0;
1554 while ( idx < cInputs
1555 && RT_SUCCESS(rc))
1556 {
1557 size_t cbInput = 0;
1558 if (cbState >= sizeof(uint32_t))
1559 {
1560 memcpy(&cbInput, pbState, sizeof(uint32_t));
1561 cbInput = RT_LE2H_U32(cbInput);
1562 pbState += sizeof(uint32_t);
1563 }
1564
1565 if ( cbInput
1566 && cbInput <= cbState)
1567 {
1568 PRTFUZZINPUTINT pInput = rtFuzzCtxInputCreate(pThis, cbInput);
1569 if (RT_LIKELY(pInput))
1570 {
1571 memcpy(&pInput->abInput[0], pbState, cbInput);
1572 RTMd5(&pInput->abInput[0], pInput->cbInput, &pInput->abMd5Hash[0]);
1573 rc = rtFuzzCtxInputAdd(pThis, pInput);
1574 if (RT_FAILURE(rc))
1575 RTMemFree(pInput);
1576 pbState += cbInput;
1577 }
1578 }
1579 else
1580 rc = VERR_INVALID_STATE;
1581
1582 idx++;
1583 }
1584
1585 if (RT_SUCCESS(rc))
1586 {
1587 *phFuzzCtx = pThis;
1588 return VINF_SUCCESS;
1589 }
1590 }
1591
1592 rtFuzzCtxDestroy(pThis);
1593 }
1594 else
1595 rc = VERR_NO_MEMORY;
1596 }
1597 else
1598 rc = VERR_INVALID_MAGIC;
1599 }
1600 else
1601 rc = VERR_INVALID_MAGIC;
1602
1603 return rc;
1604#else
1605 RT_NOREF(pvUser);
1606 return VERR_NOT_IMPLEMENTED;
1607#endif
1608}
1609
1610
1611RTDECL(int) RTFuzzCtxCreateFromStateMem(PRTFUZZCTX phFuzzCtx, const void *pvState, size_t cbState)
1612{
1613 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
1614 AssertPtrReturn(pvState, VERR_INVALID_POINTER);
1615 AssertPtrReturn(cbState, VERR_INVALID_POINTER);
1616
1617 return VERR_NOT_IMPLEMENTED;
1618}
1619
1620
1621RTDECL(int) RTFuzzCtxCreateFromStateFile(PRTFUZZCTX phFuzzCtx, const char *pszFilename)
1622{
1623 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);
1624 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1625
1626 void *pv = NULL;
1627 size_t cb = 0;
1628 int rc = RTFileReadAll(pszFilename, &pv, &cb);
1629 if (RT_SUCCESS(rc))
1630 {
1631 rc = RTFuzzCtxCreateFromStateMem(phFuzzCtx, pv, cb);
1632 RTFileReadAllFree(pv, cb);
1633 }
1634
1635 return rc;
1636}
1637
1638
1639RTDECL(uint32_t) RTFuzzCtxRetain(RTFUZZCTX hFuzzCtx)
1640{
1641 PRTFUZZCTXINT pThis = hFuzzCtx;
1642
1643 AssertPtrReturn(pThis, UINT32_MAX);
1644
1645 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
1646 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
1647 return cRefs;
1648}
1649
1650
1651RTDECL(uint32_t) RTFuzzCtxRelease(RTFUZZCTX hFuzzCtx)
1652{
1653 PRTFUZZCTXINT pThis = hFuzzCtx;
1654 if (pThis == NIL_RTFUZZCTX)
1655 return 0;
1656 AssertPtrReturn(pThis, UINT32_MAX);
1657
1658 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
1659 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
1660 if (cRefs == 0)
1661 rtFuzzCtxDestroy(pThis);
1662 return cRefs;
1663}
1664
1665
1666RTDECL(int) RTFuzzCtxQueryStats(RTFUZZCTX hFuzzCtx, PRTFUZZCTXSTATS pStats)
1667{
1668 PRTFUZZCTXINT pThis = hFuzzCtx;
1669 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1670 AssertPtrReturn(pStats, VERR_INVALID_POINTER);
1671
1672 pStats->cbMemory = ASMAtomicReadZ(&pThis->cbMemTotal);
1673 pStats->cMutations = ASMAtomicReadU64(&pThis->cMutations);
1674 return VINF_SUCCESS;
1675}
1676
1677
1678/**
1679 * Fuzzing context export callback for a single mutation.
1680 */
1681static DECLCALLBACK(int) rtFuzzCtxStateExportMutations(PAVLU64NODECORE pCore, void *pvParam)
1682{
1683 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)pCore;
1684 PCRTFUZZMUTATOR pMutator = pMutation->pMutator;
1685 PCRTFUZZEXPORTARGS pArgs = (PCRTFUZZEXPORTARGS)pvParam;
1686 RTFUZZMUTATIONSTATE MutationState;
1687
1688 MutationState.u64Id = RT_H2LE_U64(pMutation->Core.Key);
1689 if (pMutation->pMutationParent)
1690 MutationState.u64IdParent = RT_H2LE_U64(pMutation->pMutationParent->Core.Key);
1691 else
1692 MutationState.u64IdParent = RT_H2LE_U64(0);
1693 MutationState.u64OffMutation = RT_H2LE_U64(pMutation->offMutation);
1694 MutationState.cbInput = RT_H2LE_U64((uint64_t)pMutation->cbInput);
1695 MutationState.cbMutation = RT_H2LE_U64((uint64_t)pMutation->cbMutation);
1696 MutationState.u32IdMutator = RT_H2LE_U32(pMutator->uMutator);
1697 MutationState.iLvl = RT_H2LE_U32(pMutation->iLvl);
1698 MutationState.u32Magic = RT_H2LE_U32(pMutation->u32Magic);
1699
1700 int rc = pArgs->pfnExport(pMutation->pFuzzer, &MutationState, sizeof(MutationState), pArgs->pvUser);
1701 if ( RT_SUCCESS(rc)
1702 && pMutator->pfnExport)
1703 rc = pMutator->pfnExport(pMutation->pFuzzer, pMutation, &pMutation->abMutation[0], pArgs->pfnExport, pArgs->pvUser);
1704 return rc;
1705}
1706
1707
1708RTDECL(int) RTFuzzCtxStateExport(RTFUZZCTX hFuzzCtx, PFNRTFUZZCTXEXPORT pfnExport, void *pvUser)
1709{
1710 PRTFUZZCTXINT pThis = hFuzzCtx;
1711 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1712 AssertPtrReturn(pfnExport, VERR_INVALID_POINTER);
1713
1714 char aszPrngExport[_4K]; /* Should be plenty of room here. */
1715 size_t cbPrng = sizeof(aszPrngExport);
1716 int rc = RTRandAdvSaveState(pThis->hRand, &aszPrngExport[0], &cbPrng);
1717 if (RT_SUCCESS(rc))
1718 {
1719 RTFUZZCTXSTATE StateExport;
1720
1721 StateExport.u32Magic = RT_H2LE_U32(RTFUZZCTX_MAGIC);
1722 switch (pThis->enmType)
1723 {
1724 case RTFUZZCTXTYPE_BLOB:
1725 StateExport.uCtxType = RT_H2LE_U32(RTFUZZCTX_STATE_TYPE_BLOB);
1726 break;
1727 case RTFUZZCTXTYPE_STREAM:
1728 StateExport.uCtxType = RT_H2LE_U32(RTFUZZCTX_STATE_TYPE_STREAM);
1729 break;
1730 default:
1731 AssertFailed();
1732 break;
1733 }
1734 StateExport.cbPrng = RT_H2LE_U32((uint32_t)cbPrng);
1735 StateExport.cMutations = RT_H2LE_U32(pThis->cMutations);
1736 StateExport.cMutators = RT_H2LE_U32(pThis->cMutators);
1737 StateExport.fFlagsBehavioral = RT_H2LE_U32(pThis->fFlagsBehavioral);
1738 StateExport.cbInputMax = RT_H2LE_U64(pThis->cbInputMax);
1739
1740 /* Write the context state and PRNG state first. */
1741 rc = pfnExport(pThis, &StateExport, sizeof(StateExport), pvUser);
1742 if (RT_SUCCESS(rc))
1743 rc = pfnExport(pThis, &aszPrngExport[0], cbPrng, pvUser);
1744 if (RT_SUCCESS(rc))
1745 {
1746 /* Write the mutator descriptors next. */
1747 for (uint32_t i = 0; i < pThis->cMutators && RT_SUCCESS(rc); i++)
1748 {
1749 PRTFUZZMUTATOR pMutator = &pThis->paMutators[i];
1750 uint32_t cchId = (uint32_t)strlen(pMutator->pszId) + 1;
1751 uint32_t cchIdW = RT_H2LE_U32(cchId);
1752
1753 rc = pfnExport(pThis, &cchIdW, sizeof(cchIdW), pvUser);
1754 if (RT_SUCCESS(rc))
1755 rc = pfnExport(pThis, &pMutator->pszId[0], cchId, pvUser);
1756 }
1757 }
1758
1759 /* Write the mutations last. */
1760 if (RT_SUCCESS(rc))
1761 {
1762 RTFUZZEXPORTARGS Args;
1763
1764 Args.pfnExport = pfnExport;
1765 Args.pvUser = pvUser;
1766 rc = RTAvlU64DoWithAll(&pThis->TreeMutations, true /*fFromLeft*/, rtFuzzCtxStateExportMutations, &Args);
1767 }
1768 }
1769
1770 return rc;
1771}
1772
1773
1774RTDECL(int) RTFuzzCtxStateExportToMem(RTFUZZCTX hFuzzCtx, void **ppvState, size_t *pcbState)
1775{
1776 PRTFUZZCTXINT pThis = hFuzzCtx;
1777 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1778 AssertPtrReturn(ppvState, VERR_INVALID_POINTER);
1779 AssertPtrReturn(pcbState, VERR_INVALID_POINTER);
1780
1781 return VERR_NOT_IMPLEMENTED;
1782}
1783
1784
1785/**
1786 * Export to file callback.
1787 */
1788static DECLCALLBACK(int) rtFuzzCtxStateExportFile(RTFUZZCTX hFuzzCtx, const void *pvBuf, size_t cbWrite, void *pvUser)
1789{
1790 RT_NOREF(hFuzzCtx);
1791
1792 RTFILE hFile = (RTFILE)pvUser;
1793 return RTFileWrite(hFile, pvBuf, cbWrite, NULL);
1794}
1795
1796
1797RTDECL(int) RTFuzzCtxStateExportToFile(RTFUZZCTX hFuzzCtx, const char *pszFilename)
1798{
1799 PRTFUZZCTXINT pThis = hFuzzCtx;
1800 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1801 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1802
1803 RTFILE hFile;
1804 int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
1805 if (RT_SUCCESS(rc))
1806 {
1807 rc = RTFuzzCtxStateExport(hFuzzCtx, rtFuzzCtxStateExportFile, hFile);
1808 RTFileClose(hFile);
1809 if (RT_FAILURE(rc))
1810 RTFileDelete(pszFilename);
1811 }
1812
1813 return rc;
1814}
1815
1816
1817RTDECL(int) RTFuzzCtxCorpusInputAdd(RTFUZZCTX hFuzzCtx, const void *pvInput, size_t cbInput)
1818{
1819 PRTFUZZCTXINT pThis = hFuzzCtx;
1820 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1821 AssertPtrReturn(pvInput, VERR_INVALID_POINTER);
1822 AssertReturn(cbInput, VERR_INVALID_POINTER);
1823
1824 return RTFuzzCtxCorpusInputAddEx(hFuzzCtx, pvInput, cbInput, pThis->offMutStart, pThis->cbMutRange);
1825}
1826
1827
1828RTDECL(int) RTFuzzCtxCorpusInputAddEx(RTFUZZCTX hFuzzCtx, const void *pvInput, size_t cbInput,
1829 uint64_t offMutStart, uint64_t cbMutRange)
1830{
1831 PRTFUZZCTXINT pThis = hFuzzCtx;
1832 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1833 AssertPtrReturn(pvInput, VERR_INVALID_POINTER);
1834 AssertReturn(cbInput, VERR_INVALID_POINTER);
1835
1836 int rc = VINF_SUCCESS;
1837 void *pvCorpus = NULL;
1838 PRTFUZZMUTATION pMutation = rtFuzzMutationCreateEx(pThis, 0, NULL, offMutStart, cbMutRange,
1839 cbInput, &pvCorpus);
1840 if (RT_LIKELY(pMutation))
1841 {
1842 pMutation->pMutator = &g_MutatorCorpus;
1843 pMutation->cbInput = cbInput;
1844 pMutation->pvInput = pvCorpus;
1845 memcpy(pvCorpus, pvInput, cbInput);
1846 rc = rtFuzzCtxMutationAdd(pThis, pMutation);
1847 if (RT_FAILURE(rc))
1848 rtFuzzMutationDestroy(pMutation);
1849 }
1850 else
1851 rc = VERR_NO_MEMORY;
1852
1853 return rc;
1854}
1855
1856
1857RTDECL(int) RTFuzzCtxCorpusInputAddFromFile(RTFUZZCTX hFuzzCtx, const char *pszFilename)
1858{
1859 PRTFUZZCTXINT pThis = hFuzzCtx;
1860 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1861 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1862
1863 return RTFuzzCtxCorpusInputAddFromFileEx(hFuzzCtx, pszFilename, pThis->offMutStart, pThis->cbMutRange);
1864}
1865
1866
1867RTDECL(int) RTFuzzCtxCorpusInputAddFromFileEx(RTFUZZCTX hFuzzCtx, const char *pszFilename,
1868 uint64_t offMutStart, uint64_t cbMutRange)
1869{
1870 PRTFUZZCTXINT pThis = hFuzzCtx;
1871 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1872 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
1873
1874 void *pv = NULL;
1875 size_t cb = 0;
1876 int rc = RTFileReadAll(pszFilename, &pv, &cb);
1877 if (RT_SUCCESS(rc))
1878 {
1879 rc = RTFuzzCtxCorpusInputAddEx(hFuzzCtx, pv, cb, offMutStart, cbMutRange);
1880 RTFileReadAllFree(pv, cb);
1881 }
1882
1883 return rc;
1884}
1885
1886
1887RTDECL(int) RTFuzzCtxCorpusInputAddFromVfsFile(RTFUZZCTX hFuzzCtx, RTVFSFILE hVfsFile)
1888{
1889 PRTFUZZCTXINT pThis = hFuzzCtx;
1890 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1891 AssertReturn(hVfsFile != NIL_RTVFSFILE, VERR_INVALID_HANDLE);
1892
1893 return RTFuzzCtxCorpusInputAddFromVfsFileEx(hFuzzCtx, hVfsFile, pThis->offMutStart, pThis->cbMutRange);
1894}
1895
1896
1897RTDECL(int) RTFuzzCtxCorpusInputAddFromVfsFileEx(RTFUZZCTX hFuzzCtx, RTVFSFILE hVfsFile,
1898 uint64_t offMutStart, uint64_t cbMutRange)
1899{
1900 PRTFUZZCTXINT pThis = hFuzzCtx;
1901 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1902 AssertReturn(hVfsFile != NIL_RTVFSFILE, VERR_INVALID_HANDLE);
1903
1904 uint64_t cbFile = 0;
1905 void *pvCorpus = NULL;
1906 int rc = RTVfsFileQuerySize(hVfsFile, &cbFile);
1907 if (RT_SUCCESS(rc))
1908 {
1909 PRTFUZZMUTATION pMutation = rtFuzzMutationCreateEx(pThis, 0, NULL, offMutStart, cbMutRange,
1910 cbFile, &pvCorpus);
1911 if (RT_LIKELY(pMutation))
1912 {
1913 pMutation->pMutator = &g_MutatorCorpus;
1914 pMutation->cbInput = cbFile;
1915 pMutation->pvInput = pvCorpus;
1916 rc = RTVfsFileRead(hVfsFile, pvCorpus, cbFile, NULL);
1917 if (RT_SUCCESS(rc))
1918 rc = rtFuzzCtxMutationAdd(pThis, pMutation);
1919
1920 if (RT_FAILURE(rc))
1921 rtFuzzMutationDestroy(pMutation);
1922 }
1923 else
1924 rc = VERR_NO_MEMORY;
1925 }
1926
1927 return rc;
1928}
1929
1930
1931RTDECL(int) RTFuzzCtxCorpusInputAddFromDirPath(RTFUZZCTX hFuzzCtx, const char *pszDirPath)
1932{
1933 PRTFUZZCTXINT pThis = hFuzzCtx;
1934 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1935 AssertPtrReturn(pszDirPath, VERR_INVALID_POINTER);
1936
1937 RTDIR hDir;
1938 int rc = RTDirOpen(&hDir, pszDirPath);
1939 if (RT_SUCCESS(rc))
1940 {
1941 for (;;)
1942 {
1943 RTDIRENTRY DirEntry;
1944 rc = RTDirRead(hDir, &DirEntry, NULL);
1945 if (RT_FAILURE(rc))
1946 break;
1947
1948 /* Skip '.', '..' and other non-files. */
1949 if ( DirEntry.enmType != RTDIRENTRYTYPE_UNKNOWN
1950 && DirEntry.enmType != RTDIRENTRYTYPE_FILE)
1951 continue;
1952 if (RTDirEntryIsStdDotLink(&DirEntry))
1953 continue;
1954
1955 /* Compose the full path, result 'unknown' entries and skip non-files. */
1956 char szFile[RTPATH_MAX];
1957 RT_ZERO(szFile);
1958 rc = RTPathJoin(szFile, sizeof(szFile), pszDirPath, DirEntry.szName);
1959 if (RT_FAILURE(rc))
1960 break;
1961
1962 if (DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN)
1963 {
1964 RTDirQueryUnknownType(szFile, false, &DirEntry.enmType);
1965 if (DirEntry.enmType != RTDIRENTRYTYPE_FILE)
1966 continue;
1967 }
1968
1969 /* Okay, it's a file we can add. */
1970 rc = RTFuzzCtxCorpusInputAddFromFile(hFuzzCtx, szFile);
1971 if (RT_FAILURE(rc))
1972 break;
1973 }
1974 if (rc == VERR_NO_MORE_FILES)
1975 rc = VINF_SUCCESS;
1976 RTDirClose(hDir);
1977 }
1978
1979 return rc;
1980}
1981
1982
1983RTDECL(int) RTFuzzCtxCfgSetInputSeedMaximum(RTFUZZCTX hFuzzCtx, size_t cbMax)
1984{
1985 PRTFUZZCTXINT pThis = hFuzzCtx;
1986 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1987
1988 pThis->cbInputMax = cbMax;
1989 return VINF_SUCCESS;
1990}
1991
1992
1993RTDECL(size_t) RTFuzzCtxCfgGetInputSeedMaximum(RTFUZZCTX hFuzzCtx)
1994{
1995 PRTFUZZCTXINT pThis = hFuzzCtx;
1996 AssertPtrReturn(pThis, 0);
1997
1998 return pThis->cbInputMax;
1999}
2000
2001
2002RTDECL(int) RTFuzzCtxCfgSetBehavioralFlags(RTFUZZCTX hFuzzCtx, uint32_t fFlags)
2003{
2004 PRTFUZZCTXINT pThis = hFuzzCtx;
2005 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2006 AssertReturn(!(fFlags & ~RTFUZZCTX_F_BEHAVIORAL_VALID), VERR_INVALID_PARAMETER);
2007
2008 pThis->fFlagsBehavioral = fFlags;
2009 return VINF_SUCCESS;
2010}
2011
2012
2013RTDECL(uint32_t) RTFuzzCfgGetBehavioralFlags(RTFUZZCTX hFuzzCtx)
2014{
2015 PRTFUZZCTXINT pThis = hFuzzCtx;
2016 AssertPtrReturn(pThis, 0);
2017
2018 return pThis->fFlagsBehavioral;
2019}
2020
2021
2022RTDECL(int) RTFuzzCtxCfgSetTmpDirectory(RTFUZZCTX hFuzzCtx, const char *pszPathTmp)
2023{
2024 PRTFUZZCTXINT pThis = hFuzzCtx;
2025 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2026 AssertPtrReturn(pszPathTmp, VERR_INVALID_POINTER);
2027
2028 return VERR_NOT_IMPLEMENTED;
2029}
2030
2031
2032RTDECL(const char *) RTFuzzCtxCfgGetTmpDirectory(RTFUZZCTX hFuzzCtx)
2033{
2034 PRTFUZZCTXINT pThis = hFuzzCtx;
2035 AssertPtrReturn(pThis, NULL);
2036
2037 return NULL;
2038}
2039
2040
2041RTDECL(int) RTFuzzCtxCfgSetMutationRange(RTFUZZCTX hFuzzCtx, uint64_t offStart, uint64_t cbRange)
2042{
2043 PRTFUZZCTXINT pThis = hFuzzCtx;
2044 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2045
2046 pThis->offMutStart = offStart;
2047 pThis->cbMutRange = cbRange;
2048 return VINF_SUCCESS;
2049}
2050
2051
2052RTDECL(int) RTFuzzCtxReseed(RTFUZZCTX hFuzzCtx, uint64_t uSeed)
2053{
2054 PRTFUZZCTXINT pThis = hFuzzCtx;
2055 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2056
2057 RTRandAdvSeed(pThis->hRand, uSeed);
2058 return VINF_SUCCESS;
2059}
2060
2061
2062RTDECL(int) RTFuzzCtxInputGenerate(RTFUZZCTX hFuzzCtx, PRTFUZZINPUT phFuzzInput)
2063{
2064 int rc = VINF_SUCCESS;
2065 PRTFUZZCTXINT pThis = hFuzzCtx;
2066 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2067 AssertPtrReturn(phFuzzInput, VERR_INVALID_POINTER);
2068
2069 uint32_t cTries = 0;
2070 PRTFUZZMUTATION pMutationParent = rtFuzzCtxMutationPickRnd(pThis);
2071 do
2072 {
2073 uint32_t idxMutator = RTRandAdvU32Ex(pThis->hRand, 0, pThis->cMutators - 1);
2074 PCRTFUZZMUTATOR pMutator = &pThis->paMutators[idxMutator];
2075 PRTFUZZMUTATION pMutation = NULL;
2076
2077 uint64_t offStart = 0;
2078 if (!(pMutator->fFlags & RTFUZZMUTATOR_F_END_OF_BUF))
2079 {
2080 uint64_t offMax = pMutationParent->cbInput - 1;
2081 if ( pMutation->cbMutNew != UINT64_MAX
2082 && pMutation->offMutStartNew + pMutation->cbMutNew < offMax)
2083 offMax = pMutation->offMutStartNew + pMutation->cbMutNew - 1;
2084
2085 offStart = RTRandAdvU64Ex(pThis->hRand, pMutation->offMutStartNew, offMax);
2086 }
2087 else
2088 offStart = pMutationParent->cbInput;
2089
2090 rc = pMutator->pfnPrep(pThis, offStart, pMutationParent, &pMutation);
2091 if ( RT_SUCCESS(rc)
2092 && VALID_PTR(pMutation))
2093 {
2094 pMutation->pMutator = pMutator;
2095
2096 if (pThis->fFlagsBehavioral & RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS)
2097 rtFuzzCtxMutationAdd(pThis, pMutation);
2098
2099 /* Create a new input. */
2100 PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)rtFuzzCtxMemoryAlloc(pThis, sizeof(RTFUZZINPUTINT));
2101 if (RT_LIKELY(pInput))
2102 {
2103 pInput->u32Magic = 0; /** @todo */
2104 pInput->cRefs = 1;
2105 pInput->pFuzzer = pThis;
2106 pInput->pMutationTop = pMutation;
2107 RTFuzzCtxRetain(pThis);
2108
2109 rtFuzzMutationRelease(pMutationParent);
2110 *phFuzzInput = pInput;
2111 return rc;
2112 }
2113 else
2114 rc = VERR_NO_MEMORY;
2115 }
2116 } while (++cTries <= 50);
2117
2118 rtFuzzMutationRelease(pMutationParent);
2119 if (RT_SUCCESS(rc))
2120 rc = VERR_INVALID_STATE;
2121
2122 return rc;
2123}
2124
2125
2126RTDECL(int) RTFuzzInputQueryBlobData(RTFUZZINPUT hFuzzInput, void **ppv, size_t *pcb)
2127{
2128 PRTFUZZINPUTINT pThis = hFuzzInput;
2129 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2130 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
2131
2132 int rc = VINF_SUCCESS;
2133 if (!pThis->pMutationTop->pvInput)
2134 rc = rtFuzzMutationDataFinalize(pThis->pMutationTop);
2135
2136 if (RT_SUCCESS(rc))
2137 {
2138 *ppv = pThis->pMutationTop->pvInput;
2139 *pcb = pThis->pMutationTop->cbInput;
2140 }
2141
2142 return rc;
2143}
2144
2145
2146RTDECL(int) RTFuzzInputMutateStreamData(RTFUZZINPUT hFuzzInput, void *pvBuf, size_t cbBuf)
2147{
2148 PRTFUZZINPUTINT pThis = hFuzzInput;
2149 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2150 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_STREAM, VERR_INVALID_STATE);
2151
2152 RT_NOREF(pvBuf, cbBuf);
2153 return VERR_NOT_IMPLEMENTED;
2154}
2155
2156
2157RTDECL(uint32_t) RTFuzzInputRetain(RTFUZZINPUT hFuzzInput)
2158{
2159 PRTFUZZINPUTINT pThis = hFuzzInput;
2160
2161 AssertPtrReturn(pThis, UINT32_MAX);
2162
2163 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
2164 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
2165 return cRefs;
2166}
2167
2168
2169RTDECL(uint32_t) RTFuzzInputRelease(RTFUZZINPUT hFuzzInput)
2170{
2171 PRTFUZZINPUTINT pThis = hFuzzInput;
2172 if (pThis == NIL_RTFUZZINPUT)
2173 return 0;
2174 AssertPtrReturn(pThis, UINT32_MAX);
2175
2176 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
2177 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
2178 if (cRefs == 0)
2179 rtFuzzInputDestroy(pThis);
2180 return cRefs;
2181}
2182
2183
2184RTDECL(int) RTFuzzInputQueryDigestString(RTFUZZINPUT hFuzzInput, char *pszDigest, size_t cchDigest)
2185{
2186 PRTFUZZINPUTINT pThis = hFuzzInput;
2187 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2188 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
2189 AssertPtrReturn(pszDigest, VERR_INVALID_POINTER);
2190 AssertReturn(cchDigest >= RTMD5_STRING_LEN + 1, VERR_INVALID_PARAMETER);
2191
2192 int rc = VINF_SUCCESS;
2193 if (!pThis->pMutationTop->pvInput)
2194 rc = rtFuzzMutationDataFinalize(pThis->pMutationTop);
2195
2196 if (RT_SUCCESS(rc))
2197 {
2198 uint8_t abHash[RTMD5_HASH_SIZE];
2199 RTMd5(pThis->pMutationTop->pvInput, pThis->pMutationTop->cbInput, &abHash[0]);
2200 rc = RTMd5ToString(&abHash[0], pszDigest, cchDigest);
2201 }
2202
2203 return rc;
2204}
2205
2206
2207RTDECL(int) RTFuzzInputWriteToFile(RTFUZZINPUT hFuzzInput, const char *pszFilename)
2208{
2209 PRTFUZZINPUTINT pThis = hFuzzInput;
2210 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2211 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE);
2212 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
2213
2214 int rc = VINF_SUCCESS;
2215 if (!pThis->pMutationTop->pvInput)
2216 rc = rtFuzzMutationDataFinalize(pThis->pMutationTop);
2217
2218 if (RT_SUCCESS(rc))
2219 {
2220 RTFILE hFile;
2221 rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
2222 if (RT_SUCCESS(rc))
2223 {
2224 rc = RTFileWrite(hFile, pThis->pMutationTop->pvInput, pThis->pMutationTop->cbInput, NULL);
2225 AssertRC(rc);
2226 RTFileClose(hFile);
2227
2228 if (RT_FAILURE(rc))
2229 RTFileDelete(pszFilename);
2230 }
2231 }
2232
2233 return rc;
2234}
2235
2236
2237RTDECL(int) RTFuzzInputAddToCtxCorpus(RTFUZZINPUT hFuzzInput)
2238{
2239 PRTFUZZINPUTINT pThis = hFuzzInput;
2240 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2241
2242 return rtFuzzCtxMutationAdd(pThis->pFuzzer, pThis->pMutationTop);
2243}
2244
2245
2246RTDECL(int) RTFuzzInputRemoveFromCtxCorpus(RTFUZZINPUT hFuzzInput)
2247{
2248 PRTFUZZINPUTINT pThis = hFuzzInput;
2249 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2250
2251#if 0
2252 int rc = VINF_SUCCESS;
2253 PRTFUZZINTERMEDIATE pIntermediate = NULL;
2254 PRTFUZZINPUTINT pInputLoc = rtFuzzCtxInputLocate(pThis->pFuzzer, &pThis->abMd5Hash[0], true /*fExact*/,
2255 &pIntermediate);
2256 if (pInputLoc)
2257 {
2258 AssertPtr(pIntermediate);
2259 Assert(pInputLoc == pThis);
2260
2261 uint64_t u64Md5Low = *(uint64_t *)&pThis->abMd5Hash[0];
2262 RTAvlU64Remove(&pIntermediate->TreeSeedsLow, u64Md5Low);
2263 RTFuzzInputRelease(hFuzzInput);
2264 }
2265 else
2266 rc = VERR_NOT_FOUND;
2267#endif
2268
2269 return VERR_NOT_IMPLEMENTED;
2270}
2271
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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