Changeset 77482 in vbox for trunk/src/VBox/Runtime/common/fuzz
- Timestamp:
- Feb 27, 2019 1:17:24 PM (6 years ago)
- Location:
- trunk/src/VBox/Runtime/common/fuzz
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fuzz/fuzz-observer.cpp
r76553 r77482 875 875 else if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_STDIN) 876 876 { 877 rc = RTFuzzInputQuery Data(pObsThrd->hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft);877 rc = RTFuzzInputQueryBlobData(pObsThrd->hFuzzInput, (void **)&pExecCtx->pbInputCur, &pExecCtx->cbInputLeft); 878 878 if (RT_SUCCESS(rc)) 879 879 rc = rtFuzzObsExecCtxArgvPrepare(pThis, pExecCtx, NULL); … … 907 907 else 908 908 AssertFailed(); 909 910 ASMAtomicXchgBool(&pObsThrd->fKeepInput, true); 909 911 910 912 if (pThis->enmInputChan == RTFUZZOBSINPUTCHAN_FILE) … … 1066 1068 1067 1069 1068 RTDECL(int) RTFuzzObsCreate(PRTFUZZOBS phFuzzObs )1070 RTDECL(int) RTFuzzObsCreate(PRTFUZZOBS phFuzzObs, RTFUZZCTXTYPE enmType) 1069 1071 { 1070 1072 AssertPtrReturn(phFuzzObs, VERR_INVALID_POINTER); … … 1087 1089 pThis->Stats.cFuzzedInputsHang = 0; 1088 1090 pThis->Stats.cFuzzedInputsCrash = 0; 1089 rc = RTFuzzCtxCreate(&pThis->hFuzzCtx );1091 rc = RTFuzzCtxCreate(&pThis->hFuzzCtx, enmType); 1090 1092 if (RT_SUCCESS(rc)) 1091 1093 { -
trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp
r76553 r77482 44 44 #include <iprt/path.h> 45 45 #include <iprt/rand.h> 46 #include <iprt/semaphore.h> 46 47 #include <iprt/string.h> 47 48 #include <iprt/time.h> … … 57 58 /** Pointer to the internal fuzzer state. */ 58 59 typedef struct RTFUZZCTXINT *PRTFUZZCTXINT; 59 60 /** 61 * A fuzzing input seed. 62 */ 63 typedef struct RTFUZZINPUTINT 60 /** Pointer to a fuzzed mutation. */ 61 typedef struct RTFUZZMUTATION *PRTFUZZMUTATION; 62 /** Pointer to a fuzzed mutation pointer. */ 63 typedef PRTFUZZMUTATION *PPRTFUZZMUTATION; 64 /** Pointer to a const mutation. */ 65 typedef 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 */ 77 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATORPREP(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 78 PPRTFUZZMUTATION ppMutation); 79 /** Pointer to a mutator preparation callback. */ 80 typedef 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 pbBuf The buffer to work on. 90 * @param cbBuf Size of the remaining buffer. 91 */ 92 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOREXEC(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 93 uint8_t *pbBuf, size_t cbBuf); 94 /** Pointer to a mutator execution callback. */ 95 typedef FNRTFUZZCTXMUTATOREXEC *PFNRTFUZZCTXMUTATOREXEC; 96 97 98 /** 99 * A fuzzing mutator descriptor. 100 */ 101 typedef struct RTFUZZMUTATOR 102 { 103 /** Id of the mutator. */ 104 const char *pszId; 105 /** Mutator description. */ 106 const char *pszDesc; 107 /** Additional flags for the mutator, controlling the behavior. */ 108 uint64_t fFlags; 109 /** The preparation callback. */ 110 PFNRTFUZZCTXMUTATORPREP pfnPrep; 111 /** The execution callback. */ 112 PFNRTFUZZCTXMUTATOREXEC pfnExec; 113 } RTFUZZMUTATOR; 114 /** Pointer to a fuzzing mutator descriptor. */ 115 typedef RTFUZZMUTATOR *PRTFUZZMUTATOR; 116 /** Pointer to a const fuzzing mutator descriptor. */ 117 typedef const RTFUZZMUTATOR *PCRTFUZZMUTATOR; 118 119 /** Mutator always works from the end of the buffer (no starting offset generation). */ 120 #define RTFUZZMUTATOR_F_END_OF_BUF RT_BIT_64(0) 121 /** Default flags. */ 122 #define RTFUZZMUTATOR_F_DEFAULT (0) 123 124 125 /** 126 * A fuzzed mutation. 127 */ 128 typedef struct RTFUZZMUTATION 64 129 { 65 130 /** The AVL tree core. */ 66 131 AVLU64NODECORE Core; 67 /** Node for the global list. */68 RTLISTNODE NdInputs;132 /** Magic identifying this structure. */ 133 uint32_t u32Magic; 69 134 /** Reference counter. */ 70 135 volatile uint32_t cRefs; 71 /** @todo add magic here (unused padding space on 64-bit hosts). */ 136 /** The fuzzer this mutation belongs to. */ 137 PRTFUZZCTXINT pFuzzer; 138 /** Parent mutation (reference is held), NULL means root or original data. */ 139 PCRTFUZZMUTATION pMutationParent; 140 /** Mutation level. */ 141 uint32_t iLvl; 142 /** The mutator causing this mutation, NULL if original input data. */ 143 PCRTFUZZMUTATOR pMutator; 144 /** Byte offset where the mutation starts. */ 145 uint64_t offMutation; 146 /** Size of the generated input data in bytes after the mutation was applied. */ 147 size_t cbInput; 148 /** Mutation dependent data. */ 149 union 150 { 151 /** Array of bytes making up the corups, variable in size. */ 152 uint8_t abCorpus[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION]; 153 /** Bit flip mutation, which bit to flip. */ 154 uint32_t idxBitFlip; 155 /** Byte replace, the byte to replace with. */ 156 uint8_t bByteReplace; 157 /** Array of bytes to insert/append, variable in size. */ 158 uint8_t abAdd[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION]; 159 } u; 160 } RTFUZZMUTATION; 161 162 163 /** 164 * A fuzzing input seed. 165 */ 166 typedef struct RTFUZZINPUTINT 167 { 168 /** Magic identifying this structure. */ 169 uint32_t u32Magic; 170 /** Reference counter. */ 171 volatile uint32_t cRefs; 72 172 /** The fuzzer this input belongs to. */ 73 173 PRTFUZZCTXINT pFuzzer; 74 /** Complete MD5 hash of the input data. */ 75 uint8_t abMd5Hash[RTMD5_HASH_SIZE]; 76 /** Size of the input data. */ 77 size_t cbInput; 78 /** Input data - variable in size. */ 79 uint8_t abInput[1]; 174 /** The top mutation to work from (reference held). */ 175 PRTFUZZMUTATION pMutationTop; 176 /** Fuzzer context type dependent data. */ 177 union 178 { 179 /** Blob data. */ 180 struct 181 { 182 /** Size to allocate initially. */ 183 size_t cbAlloc; 184 /** Input data size. */ 185 size_t cbInput; 186 /** Pointer to the input data if created. */ 187 void *pvInput; 188 } Blob; 189 /** Stream state. */ 190 struct 191 { 192 /** Number of bytes seen so far. */ 193 size_t cbSeen; 194 } Stream; 195 } u; 196 /** Array holding all the individual mutations, variable in size. */ 197 PCRTFUZZMUTATION apMutations[1]; 80 198 } RTFUZZINPUTINT; 81 199 /** Pointer to the internal input state. */ … … 84 202 typedef PRTFUZZINPUTINT *PPRTFUZZINPUTINT; 85 203 86 87 /**88 * Intermediate indexing structure.89 */90 typedef struct RTFUZZINTERMEDIATE91 {92 /** The AVL tree core. */93 AVLU64NODECORE Core;94 /** The AVL tree for indexing the input seeds (keyed by the lower half of the MD5). */95 AVLU64TREE TreeSeedsLow;96 } RTFUZZINTERMEDIATE;97 /** Pointer to an intermediate indexing state. */98 typedef RTFUZZINTERMEDIATE *PRTFUZZINTERMEDIATE;99 /** Pointer to an intermediate indexing state pointer. */100 typedef PRTFUZZINTERMEDIATE *PPRTFUZZINTERMEDIATE;101 204 102 205 /** … … 111 214 /** The random number generator. */ 112 215 RTRAND hRand; 113 /** The AVL tree for indexing the input seeds (keyed by the upper half of the MD5). */ 114 AVLU64TREE TreeSeedsHigh; 115 /** Sequential list of all inputs. */ 116 RTLISTANCHOR LstInputs; 216 /** Fuzzing context type. */ 217 RTFUZZCTXTYPE enmType; 218 /** Semaphore protecting the mutations tree. */ 219 RTSEMRW hSemRwMutations; 220 /** The AVL tree for indexing the mutations (keyed by counter). */ 221 AVLU64TREE TreeMutations; 117 222 /** Number of inputs currently in the tree. */ 118 uint32_t cInputs;223 volatile uint64_t cMutations; 119 224 /** The maximum size of one input seed to generate. */ 120 225 size_t cbInputMax; 121 226 /** Behavioral flags. */ 122 227 uint32_t fFlagsBehavioral; 228 /** Number of enabled mutators. */ 229 uint32_t cMutators; 230 /** Pointer to the mutator descriptors. */ 231 PRTFUZZMUTATOR paMutators; 232 /** Total number of bytes of memory currently allocated in total for this context. */ 233 volatile size_t cbMemTotal; 123 234 } RTFUZZCTXINT; 124 125 126 /**127 * Available mutators enum.128 */129 typedef enum RTFUZZCTXMUTATOR130 {131 /** Invalid mutator, not used. */132 RTFUZZCTXMUTATOR_INVALID = 0,133 /** Flips a single bit in the input. */134 RTFUZZCTXMUTATOR_BIT_FLIP,135 /** Replaces a single byte in the input. */136 RTFUZZCTXMUTATOR_BYTE_REPLACE,137 /** Inserts a byte sequence into the input. */138 RTFUZZCTXMUTATOR_BYTE_SEQUENCE_INSERT,139 /** Appends a byte sequence to the input. */140 RTFUZZCTXMUTATOR_BYTE_SEQUENCE_APPEND,141 /** Deletes a single byte from the input. */142 RTFUZZCTXMUTATOR_BYTE_DELETE,143 /** Deletes a sequence of bytes from the input. */144 RTFUZZCTXMUTATOR_BYTE_SEQUENCE_DELETE,145 /** Last valid mutator. */146 RTFUZZCTXMUTATOR_LAST = RTFUZZCTXMUTATOR_BYTE_SEQUENCE_DELETE,147 /** 32bit hack. */148 RTFUZZCTXMUTATOR_32BIT_HACK = 0x7fffffff149 } RTFUZZCTXMUTATOR;150 /** Pointer to a mutator enum. */151 typedef RTFUZZCTXMUTATOR *PRTFUZZCTXMUTATOR;152 235 153 236 … … 173 256 174 257 /** 175 * Mutator callback. 176 * 177 * @returns IPRT status code. 178 * @param pThis The fuzzer context instance. 179 * @param pvBuf The input buffer to mutate. 180 * @param cbBuf Size of the buffer in bytes. 181 * @param ppInputMutated Where to store the pointer to the mutated input success. 182 */ 183 typedef DECLCALLBACK(int) FNRTFUZZCTXMUTATOR(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated); 184 /** Pointer to a mutator callback. */ 185 typedef FNRTFUZZCTXMUTATOR *PFNRTFUZZCTXMUTATOR; 258 * Fuzzing context memory header. 259 */ 260 typedef struct RTFUZZMEMHDR 261 { 262 /** Size of the memory area following. */ 263 size_t cb; 264 #if HC_ARCH_BITS == 32 265 /** Some padding. */ 266 uint32_t uPadding0; 267 #elif HC_ARCH_BITS == 64 268 #else 269 /** Some padding. */ 270 uint64_t uPadding0; 271 # error "Port me" 272 #endif 273 } RTFUZZMEMHDR; 274 /** Pointer to a memory header. */ 275 typedef RTFUZZMEMHDR *PRTFUZZMEMHDR; 276 186 277 187 278 … … 189 280 * Internal Functions * 190 281 *********************************************************************************************************************************/ 191 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 192 PPRTFUZZINPUTINT ppInputMutated); 193 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 194 PPRTFUZZINPUTINT ppInputMutated); 195 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 196 PPRTFUZZINPUTINT ppInputMutated); 197 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 198 PPRTFUZZINPUTINT ppInputMutated); 199 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 200 PPRTFUZZINPUTINT ppInputMutated); 201 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, 202 PPRTFUZZINPUTINT ppInputMutated); 203 282 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 283 PPRTFUZZMUTATION ppMutation); 284 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 285 PPRTFUZZMUTATION ppMutation); 286 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 287 PPRTFUZZMUTATION ppMutation); 288 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 289 PPRTFUZZMUTATION ppMutation); 290 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 291 PPRTFUZZMUTATION ppMutation); 292 293 static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 294 uint8_t *pbBuf, size_t cbBuf); 295 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 296 uint8_t *pbBuf, size_t cbBuf); 297 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 298 uint8_t *pbBuf, size_t cbBuf); 299 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 300 uint8_t *pbBuf, size_t cbBuf); 301 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 302 uint8_t *pbBuf, size_t cbBuf); 303 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 304 uint8_t *pbBuf, size_t cbBuf); 204 305 205 306 /********************************************************************************************************************************* … … 207 308 *********************************************************************************************************************************/ 208 309 /** 310 * The special corpus mutator for the original data. 311 */ 312 static RTFUZZMUTATOR const g_MutatorCorpus = 313 { 314 /** pszId */ 315 "Corpus", 316 /** pszDesc */ 317 "Special mutator, which is assigned to the initial corpus", 318 /** fFlags */ 319 RTFUZZMUTATOR_F_DEFAULT, 320 /** pfnPrep */ 321 NULL, 322 /** pfnExec */ 323 rtFuzzCtxMutatorCorpusExec 324 }; 325 326 /** 209 327 * Array of all available mutators. 210 328 */ 211 static PFNRTFUZZCTXMUTATOR const g_apfnMutators[] = 212 { 213 NULL, 214 rtFuzzCtxMutatorBitFlip, 215 rtFuzzCtxMutatorByteReplace, 216 rtFuzzCtxMutatorByteSequenceInsert, 217 rtFuzzCtxMutatorByteSequenceAppend, 218 rtFuzzCtxMutatorByteDelete, 219 rtFuzzCtxMutatorByteSequenceDelete, 220 NULL 329 static RTFUZZMUTATOR const g_aMutators[] = 330 { 331 /* pszId pszDesc fFlags pfnPrep pfnExec */ 332 { "BitFlip", "Flips a single bit in the input", RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorBitFlipPrep, rtFuzzCtxMutatorBitFlipExec}, 333 { "ByteReplace", "Replaces a single byte in the input", RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteReplacePrep, rtFuzzCtxMutatorByteReplaceExec}, 334 { "ByteSeqIns", "Inserts a byte sequence in the input", RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec}, 335 { "ByteSeqApp", "Appends a byte sequence to the input", RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec}, 336 { "ByteDelete", "Deletes a single byte sequence from the input", RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteDeletePrep, rtFuzzCtxMutatorByteDeleteExec}, 337 { "ByteSeqDel", "Deletes a byte sequence from the input", RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceDeletePrep, rtFuzzCtxMutatorByteSequenceDeleteExec} 221 338 }; 222 339 223 340 224 225 /** 226 * Tries to locate an input seed with the given input MD5 seed. 227 * 228 * @returns Pointer to the input seed on success or NULL if not found. 341 /** 342 * Allocates the given number of bytes. 343 * 344 * @returns Pointer to the allocated memory 229 345 * @param pThis The fuzzer context instance. 230 * @param pbMd5Hash The MD5 hash to search for. 231 * @param fExact Flag whether to search for an exact match or return the next best fit if no match exists. 232 * @param ppIntermediate Where to store the pointer to the intermediate layer upon success, optional. 233 */ 234 static PRTFUZZINPUTINT rtFuzzCtxInputLocate(PRTFUZZCTXINT pThis, uint8_t *pbMd5Hash, bool fExact, PPRTFUZZINTERMEDIATE ppIntermediate) 235 { 236 PRTFUZZINPUTINT pInput = NULL; 237 uint64_t u64Md5High = *(uint64_t *)&pbMd5Hash[RTMD5_HASH_SIZE / 2]; 238 uint64_t u64Md5Low = *(uint64_t *)&pbMd5Hash[0]; 239 PRTFUZZINTERMEDIATE pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64Get(&pThis->TreeSeedsHigh, u64Md5High); 240 if (!fExact && !pIntermediate) 241 pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64GetBestFit(&pThis->TreeSeedsHigh, u64Md5High, true /*fAbove*/); 242 if (!fExact && !pIntermediate) 243 pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64GetBestFit(&pThis->TreeSeedsHigh, u64Md5High, false /*fAbove*/); 244 245 if (pIntermediate) 246 { 247 /* 2nd level lookup. */ 248 pInput = (PRTFUZZINPUTINT)RTAvlU64Get(&pIntermediate->TreeSeedsLow, u64Md5Low); 249 if (!fExact && !pInput) 250 pInput = (PRTFUZZINPUTINT)RTAvlU64GetBestFit(&pIntermediate->TreeSeedsLow, u64Md5Low, true /*fAbove*/); 251 if (!fExact && !pInput) 252 pInput = (PRTFUZZINPUTINT)RTAvlU64GetBestFit(&pIntermediate->TreeSeedsLow, u64Md5Low, false /*fAbove*/); 253 } 254 255 if (ppIntermediate) 256 *ppIntermediate = pIntermediate; 257 258 return pInput; 259 } 260 261 262 /** 263 * Adds the given input to the corpus of the given fuzzer context. 346 * @param cb How much to allocate. 347 */ 348 static void *rtFuzzCtxMemoryAlloc(PRTFUZZCTXINT pThis, size_t cb) 349 { 350 PRTFUZZMEMHDR pMemHdr = (PRTFUZZMEMHDR)RTMemAllocZ(cb + sizeof(RTFUZZMEMHDR)); 351 if (RT_LIKELY(pMemHdr)) 352 { 353 size_t cbIgn = 0; 354 pMemHdr->cb = cb; 355 ASMAtomicAddSize(&pThis->cbMemTotal, cb + sizeof(RTFUZZMEMHDR), &cbIgn); RT_NOREF(cbIgn); 356 return pMemHdr + 1; 357 } 358 359 return NULL; 360 } 361 362 363 /** 364 * Frees the given memory. 365 * 366 * @returns nothing. 367 * @param pThis The fuzzer context instance. 368 * @param pv Pointer to the memory area to free. 369 */ 370 static void rtFuzzCtxMemoryFree(PRTFUZZCTXINT pThis, void *pv) 371 { 372 PRTFUZZMEMHDR pMemHdr = ((PRTFUZZMEMHDR)pv) - 1; 373 374 size_t cbIgn = 0; 375 ASMAtomicSubSize(&pThis->cbMemTotal, pMemHdr->cb + sizeof(RTFUZZMEMHDR), &cbIgn); RT_NOREF(cbIgn); 376 RTMemFree(pMemHdr); 377 } 378 379 380 /** 381 * Retains an external reference to the given mutation. 382 * 383 * @returns New reference count on success. 384 * @param pMutation The mutation to retain. 385 */ 386 static uint32_t rtFuzzMutationRetain(PRTFUZZMUTATION pMutation) 387 { 388 uint32_t cRefs = ASMAtomicIncU32(&pMutation->cRefs); 389 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pMutation)); 390 return cRefs; 391 } 392 393 #if 0 /* unused */ 394 /** 395 * Releases an external reference from the given mutation. 396 * 397 * @returns New reference count on success. 398 * @param pMutation The mutation to retain. 399 */ 400 static uint32_t rtFuzzMutationRelease(PRTFUZZMUTATION pMutation) 401 { 402 uint32_t cRefs = ASMAtomicDecU32(&pMutation->cRefs); 403 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pMutation)); 404 return cRefs; 405 } 406 #endif 407 408 /** 409 * Adds the given mutation to the corpus of the given fuzzer context. 264 410 * 265 411 * @returns IPRT status code. 266 412 * @param pThis The fuzzer context instance. 267 * @param p Input The inputto add.268 */ 269 static int rtFuzzCtx InputAdd(PRTFUZZCTXINT pThis, PRTFUZZINPUTINT pInput)413 * @param pMutation The mutation to add. 414 */ 415 static int rtFuzzCtxMutationAdd(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation) 270 416 { 271 417 int rc = VINF_SUCCESS; 272 uint64_t u64Md5High = *(uint64_t *)&pInput->abMd5Hash[RTMD5_HASH_SIZE / 2]; 273 uint64_t u64Md5Low = *(uint64_t *)&pInput->abMd5Hash[0]; 274 275 pInput->Core.Key = u64Md5Low; 276 PRTFUZZINTERMEDIATE pIntermediate = (PRTFUZZINTERMEDIATE)RTAvlU64Get(&pThis->TreeSeedsHigh, u64Md5High); 277 if (!pIntermediate) 278 { 279 pIntermediate = (PRTFUZZINTERMEDIATE)RTMemAllocZ(sizeof(*pIntermediate)); 280 if (RT_LIKELY(pIntermediate)) 418 419 pMutation->Core.Key = ASMAtomicIncU64(&pThis->cMutations) - 1; 420 rc = RTSemRWRequestWrite(pThis->hSemRwMutations, RT_INDEFINITE_WAIT); 421 AssertRC(rc); RT_NOREF(rc); 422 bool fIns = RTAvlU64Insert(&pThis->TreeMutations, &pMutation->Core); 423 Assert(fIns); 424 rc = RTSemRWReleaseWrite(pThis->hSemRwMutations); 425 AssertRC(rc); RT_NOREF(rc); 426 427 return rc; 428 } 429 430 431 /** 432 * Returns a random mutation from the corpus of the given fuzzer context. 433 * 434 * @returns Pointer to a randomly picked mutation (reference count is increased). 435 * @param pThis The fuzzer context instance. 436 */ 437 static PRTFUZZMUTATION rtFuzzCtxMutationPickRnd(PRTFUZZCTXINT pThis) 438 { 439 uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 0, ASMAtomicReadU64(&pThis->cMutations)); 440 441 int rc = RTSemRWRequestRead(pThis->hSemRwMutations, RT_INDEFINITE_WAIT); 442 AssertRC(rc); RT_NOREF(rc); 443 444 /* 445 * Using best fit getter here as there might be a racing mutation insertion and the mutation counter has increased 446 * already but the mutation is not yet in the tree. 447 */ 448 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)RTAvlU64GetBestFit(&pThis->TreeMutations, idxMutation, false /*fAbove*/); 449 AssertPtr(pMutation); 450 451 /* Increase reference count of the mutation. */ 452 rtFuzzMutationRetain(pMutation); 453 rc = RTSemRWReleaseRead(pThis->hSemRwMutations); 454 AssertRC(rc); RT_NOREF(rc); 455 456 return pMutation; 457 } 458 459 460 /** 461 * Creates a new mutation capable of holding the additional number of bytes. 462 * 463 * @returns Pointer to the newly created mutation or NULL if out of memory. 464 * @param pThis The fuzzer context instance. 465 * @param offMutation The starting offset for the mutation. 466 * @param pMutationParent The parent mutation, can be NULL. 467 * @param cbAdditional Additional number of bytes to allocate after the core structure. 468 */ 469 static PRTFUZZMUTATION rtFuzzMutationCreate(PRTFUZZCTXINT pThis, uint64_t offMutation, PRTFUZZMUTATION pMutationParent, size_t cbAdditional) 470 { 471 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)rtFuzzCtxMemoryAlloc(pThis, sizeof(RTFUZZMUTATION) + cbAdditional); 472 if (RT_LIKELY(pMutation)) 473 { 474 pMutation->u32Magic = 0; /** @todo */ 475 pMutation->pFuzzer = pThis; 476 pMutation->cRefs = 1; 477 pMutation->iLvl = 0; 478 pMutation->offMutation = offMutation; 479 pMutation->pMutationParent = pMutationParent; 480 481 if (pMutationParent) 482 pMutation->iLvl = pMutationParent->iLvl + 1; 483 } 484 485 return pMutation; 486 } 487 488 489 /** 490 * Destroys the given mutation. 491 * 492 * @returns nothing. 493 * @param pMutation The mutation to destroy. 494 */ 495 static void rtFuzzMutationDestroy(PRTFUZZMUTATION pMutation) 496 { 497 rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation); 498 } 499 500 501 /** 502 * Destorys the given fuzzer context freeing all allocated resources. 503 * 504 * @returns nothing. 505 * @param pThis The fuzzer context instance. 506 */ 507 static void rtFuzzCtxDestroy(PRTFUZZCTXINT pThis) 508 { 509 RT_NOREF(pThis); 510 } 511 512 513 static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 514 uint8_t *pbBuf, size_t cbBuf) 515 { 516 RT_NOREF(pThis, cbBuf); 517 memcpy(pbBuf, &pMutation->u.abCorpus[0], pMutation->cbInput); 518 return VINF_SUCCESS; 519 } 520 521 522 /** 523 * Mutator callback - flips a single bit in the input. 524 */ 525 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 526 PPRTFUZZMUTATION ppMutation) 527 { 528 int rc = VINF_SUCCESS; 529 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/); 530 if (RT_LIKELY(pMutation)) 531 { 532 pMutation->cbInput = pMutationParent->cbInput; /* Bit flips don't change the input size. */ 533 pMutation->u.idxBitFlip = RTRandAdvS32Ex(pThis->hRand, 0, (pMutationParent->cbInput - offStart) * 8 - 1); 534 *ppMutation = pMutation; 535 } 536 else 537 rc = VERR_NO_MEMORY; 538 539 return rc; 540 } 541 542 543 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlipExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 544 uint8_t *pbBuf, size_t cbBuf) 545 { 546 RT_NOREF(pThis, cbBuf); 547 ASMBitToggle(pbBuf, pMutation->u.idxBitFlip); 548 return VINF_SUCCESS; 549 } 550 551 552 /** 553 * Mutator callback - replaces a single byte in the input. 554 */ 555 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 556 PPRTFUZZMUTATION ppMutation) 557 { 558 int rc = VINF_SUCCESS; 559 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/); 560 if (RT_LIKELY(pMutation)) 561 { 562 pMutation->cbInput = pMutationParent->cbInput; /* Byte replacements don't change the input size. */ 563 RTRandAdvBytes(pThis->hRand, &pMutation->u.bByteReplace, 1); /** @todo: Filter out same values. */ 564 *ppMutation = pMutation; 565 } 566 else 567 rc = VERR_NO_MEMORY; 568 569 return rc; 570 } 571 572 573 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 574 uint8_t *pbBuf, size_t cbBuf) 575 { 576 RT_NOREF(pThis, cbBuf); 577 *pbBuf = pMutation->u.bByteReplace; 578 return VINF_SUCCESS; 579 } 580 581 582 /** 583 * Mutator callback - inserts a byte sequence into the input. 584 */ 585 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 586 PPRTFUZZMUTATION ppMutation) 587 { 588 int rc = VINF_SUCCESS; 589 if (pMutationParent->cbInput < pThis->cbInputMax) 590 { 591 size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, pMutationParent->cbInput + 1, pThis->cbInputMax); 592 size_t cbInsert = cbInputMutated - pMutationParent->cbInput; 593 594 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, cbInsert); 595 if (RT_LIKELY(pMutation)) 281 596 { 282 pIntermediate->Core.Key = u64Md5High; 283 pIntermediate->TreeSeedsLow = NULL; 284 bool fIns = RTAvlU64Insert(&pThis->TreeSeedsHigh, &pIntermediate->Core); 285 Assert(fIns); RT_NOREF(fIns); 597 pMutation->cbInput = cbInputMutated; 598 RTRandAdvBytes(pThis->hRand, &pMutation->u.abAdd[0], cbInsert); 599 *ppMutation = pMutation; 286 600 } 287 601 else … … 289 603 } 290 604 291 if (RT_SUCCESS(rc)) 292 { 293 AssertPtr(pIntermediate); 294 bool fIns = RTAvlU64Insert(&pIntermediate->TreeSeedsLow, &pInput->Core); 295 if (!fIns) 296 rc = VERR_ALREADY_EXISTS; 297 else 605 return rc; 606 } 607 608 609 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 610 uint8_t *pbBuf, size_t cbBuf) 611 { 612 RT_NOREF(pThis); 613 size_t cbInsert = pMutation->cbInput - pMutation->pMutationParent->cbInput; 614 615 /* Move any remaining data to the end. */ 616 if (cbBuf) 617 memmove(pbBuf + cbInsert, pbBuf, cbBuf); 618 619 memcpy(pbBuf, &pMutation->u.abAdd[0], cbInsert); 620 return VINF_SUCCESS; 621 } 622 623 624 /** 625 * Mutator callback - deletes a single byte in the input. 626 */ 627 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 628 PPRTFUZZMUTATION ppMutation) 629 { 630 int rc = VINF_SUCCESS; 631 if (pMutationParent->cbInput - offStart >= 1) 632 { 633 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/); 634 if (RT_LIKELY(pMutation)) 298 635 { 299 RTListAppend(&pThis->LstInputs, &pInput->NdInputs); 300 pThis->cInputs++; 301 RTFuzzInputRetain(pInput); 302 } 303 } 304 305 return rc; 306 } 307 308 309 /** 310 * Returns a random input from the corpus of the given fuzzer context. 311 * 312 * @returns Pointer to a randomly picked input. 313 * @param pThis The fuzzer context instance. 314 */ 315 static PRTFUZZINPUTINT rtFuzzCtxInputPickRnd(PRTFUZZCTXINT pThis) 316 { 317 /* Generate a random MD5 hash and do a non exact localisation. */ 318 uint8_t abDigestRnd[RTMD5_HASH_SIZE]; 319 RTRandAdvBytes(pThis->hRand, &abDigestRnd[0], sizeof(abDigestRnd)); 320 321 return rtFuzzCtxInputLocate(pThis, &abDigestRnd[0], false /*fExact*/, NULL /*ppIntermediate*/); 322 } 323 324 325 /** 326 * Clones a given input. 327 * 328 * @returns Pointer to the cloned input or NULL if out of memory. 329 * @param pThis The fuzzer context instance. 330 * @param pvBuf The buffer to clone. 331 * @param cbBuf Size of the buffer in bytes. 332 */ 333 static PRTFUZZINPUTINT rtFuzzCtxInputClone(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf) 334 { 335 PRTFUZZINPUTINT pInpClone = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbBuf])); 336 if (RT_LIKELY(pInpClone)) 337 { 338 pInpClone->cRefs = 1; 339 pInpClone->pFuzzer = pThis, 340 pInpClone->cbInput = cbBuf; 341 memcpy(&pInpClone->abInput[0], pvBuf, cbBuf); 342 } 343 344 return pInpClone; 345 } 346 347 348 /** 349 * Creates an empty input seed capable of holding the given number of bytes. 350 * 351 * @returns Pointer to the newly created input seed. 352 * @param pThis The fuzzer context instance. 353 * @param cbInput Input seed size in bytes. 354 */ 355 static PRTFUZZINPUTINT rtFuzzCtxInputCreate(PRTFUZZCTXINT pThis, size_t cbInput) 356 { 357 PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbInput])); 358 if (RT_LIKELY(pInput)) 359 { 360 pInput->pFuzzer = pThis; 361 pInput->cRefs = 1; 362 pInput->cbInput = cbInput; 363 } 364 365 return pInput; 366 } 367 368 369 /** 370 * Destroys the given input. 371 * 372 * @returns nothing. 373 * @param pInput The input to destroy. 374 */ 375 static void rtFuzzInputDestroy(PRTFUZZINPUTINT pInput) 376 { 377 RTMemFree(pInput); 378 } 379 380 381 /** 382 * Destorys the given fuzzer context freeing all allocated resources. 383 * 384 * @returns nothing. 385 * @param pThis The fuzzer context instance. 386 */ 387 static void rtFuzzCtxDestroy(PRTFUZZCTXINT pThis) 388 { 389 RT_NOREF(pThis); 390 } 391 392 393 /** 394 * Mutator callback - flips a single bit in the input. 395 */ 396 static DECLCALLBACK(int) rtFuzzCtxMutatorBitFlip(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 397 { 398 int rc = VINF_SUCCESS; 399 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf); 400 if (RT_LIKELY(pInputMutated)) 401 { 402 int32_t iBit = RTRandAdvS32Ex(pThis->hRand, 0, (uint32_t)cbBuf * 8 - 1); 403 ASMBitToggle(&pInputMutated->abInput[0], iBit); 404 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 405 *ppInputMutated = pInputMutated; 406 } 407 else 408 rc = VERR_NO_MEMORY; 409 410 return rc; 411 } 412 413 414 /** 415 * Mutator callback - replaces a single byte in the input. 416 */ 417 static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplace(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 418 { 419 int rc = VINF_SUCCESS; 420 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputClone(pThis, pvBuf, cbBuf); 421 if (RT_LIKELY(pInputMutated)) 422 { 423 uint8_t *pbBuf = (uint8_t *)pvBuf; 424 uint32_t offByte = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1); 425 RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offByte], 1); 426 if (pbBuf[offByte] != pInputMutated->abInput[offByte]) 427 { 428 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 429 *ppInputMutated = pInputMutated; 430 } 431 else 432 RTMemFree(pInputMutated); 433 } 434 else 435 rc = VERR_NO_MEMORY; 436 437 return rc; 438 } 439 440 441 /** 442 * Mutator callback - inserts a byte sequence into the input. 443 */ 444 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsert(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 445 { 446 int rc = VINF_SUCCESS; 447 if (cbBuf < pThis->cbInputMax) 448 { 449 size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, (uint32_t)cbBuf + 1, (uint32_t)pThis->cbInputMax); 450 size_t cbInsert = cbInputMutated - cbBuf; 451 uint32_t offInsert = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf); 452 uint8_t *pbBuf = (uint8_t *)pvBuf; 453 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated); 454 if (RT_LIKELY(pInputMutated)) 455 { 456 if (offInsert) 457 memcpy(&pInputMutated->abInput[0], pbBuf, offInsert); 458 RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[offInsert], cbInsert); 459 memcpy(&pInputMutated->abInput[offInsert + cbInsert], &pbBuf[offInsert], cbBuf - offInsert); 460 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 461 *ppInputMutated = pInputMutated; 636 pMutation->cbInput = pMutationParent->cbInput - 1; 637 *ppMutation = pMutation; 462 638 } 463 639 else … … 469 645 470 646 471 /** 472 * Mutator callback - appends a byte sequence to the input. 473 */ 474 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceAppend(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 647 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 648 uint8_t *pbBuf, size_t cbBuf) 649 { 650 RT_NOREF(pThis, pMutation); 651 652 /* Just move the residual data to the front. */ 653 memmove(pbBuf, pbBuf + 1, cbBuf - 1); 654 return VINF_SUCCESS; 655 } 656 657 658 659 /** 660 * Mutator callback - deletes a byte sequence in the input. 661 */ 662 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 663 PPRTFUZZMUTATION ppMutation) 475 664 { 476 665 int rc = VINF_SUCCESS; 477 if ( cbBuf < pThis->cbInputMax)478 { 479 size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, (uint32_t)cbBuf + 1, (uint32_t)pThis->cbInputMax);480 size_t cbInsert = cbInputMutated - cbBuf; 481 PRTFUZZ INPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated);482 if (RT_LIKELY(p InputMutated))666 if (pMutationParent->cbInput > 1) 667 { 668 size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, offStart, pMutationParent->cbInput - 1); 669 670 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 0 /*cbAdditional*/); 671 if (RT_LIKELY(pMutation)) 483 672 { 484 memcpy(&pInputMutated->abInput[0], pvBuf, cbBuf); 485 RTRandAdvBytes(pThis->hRand, &pInputMutated->abInput[cbBuf], cbInsert); 486 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 487 *ppInputMutated = pInputMutated; 673 pMutation->cbInput = cbInputMutated; 674 *ppMutation = pMutation; 488 675 } 489 676 else … … 495 682 496 683 497 /** 498 * Mutator callback - deletes a single byte in the input. 499 */ 500 static DECLCALLBACK(int) rtFuzzCtxMutatorByteDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated) 501 { 502 int rc = VINF_SUCCESS; 503 if (cbBuf > 1) 504 { 505 uint32_t offDelete = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1); 506 uint8_t *pbBuf = (uint8_t *)pvBuf; 507 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbBuf - 1); 508 if (RT_LIKELY(pInputMutated)) 684 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, 685 uint8_t *pbBuf, size_t cbBuf) 686 { 687 RT_NOREF(pThis); 688 Assert(pMutation->pMutationParent->cbInput > pMutation->cbInput); 689 size_t cbDel = pMutation->pMutationParent->cbInput - pMutation->cbInput; 690 691 /* Just move the residual data to the front. */ 692 memmove(pbBuf, pbBuf + cbDel, cbBuf - cbDel); 693 return VINF_SUCCESS; 694 } 695 696 697 /** 698 * Creates an empty fuzzing context. 699 * 700 * @returns IPRT status code. 701 * @param ppThis Where to store the pointer to the internal fuzzing context instance on success. 702 * @param enmType Fuzzing context type. 703 */ 704 static int rtFuzzCtxCreateEmpty(PRTFUZZCTXINT *ppThis, RTFUZZCTXTYPE enmType) 705 { 706 int rc; 707 PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis)); 708 if (RT_LIKELY(pThis)) 709 { 710 pThis->u32Magic = RTFUZZCTX_MAGIC; 711 pThis->cRefs = 1; 712 pThis->enmType = enmType; 713 pThis->TreeMutations = NULL; 714 pThis->cbInputMax = UINT32_MAX; 715 pThis->cMutations = 0; 716 pThis->fFlagsBehavioral = 0; 717 pThis->cbMemTotal = 0; 718 719 /* Copy the default mutator descriptors over. */ 720 pThis->paMutators = (PRTFUZZMUTATOR)RTMemAllocZ(RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR)); 721 if (RT_LIKELY(pThis->paMutators)) 509 722 { 510 if (offDelete) 511 memcpy(&pInputMutated->abInput[0], pbBuf, offDelete); 512 if (offDelete < cbBuf - 1) 513 memcpy(&pInputMutated->abInput[offDelete], &pbBuf[offDelete + 1], cbBuf - offDelete - 1); 514 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]); 515 *ppInputMutated = pInputMutated; 723 pThis->cMutators = RT_ELEMENTS(g_aMutators); 724 memcpy(&pThis->paMutators[0], &g_aMutators[0], RT_ELEMENTS(g_aMutators) * sizeof(RTFUZZMUTATOR)); 725 726 rc = RTSemRWCreate(&pThis->hSemRwMutations); 727 if (RT_SUCCESS(rc)) 728 { 729 rc = RTRandAdvCreateParkMiller(&pThis->hRand); 730 if (RT_SUCCESS(rc)) 731 { 732 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS()); 733 *ppThis = pThis; 734 return VINF_SUCCESS; 735 } 736 737 RTSemRWDestroy(pThis->hSemRwMutations); 738 } 516 739 } 517 740 else 518 741 rc = VERR_NO_MEMORY; 519 }520 521 return rc;522 }523 524 525 /**526 * Mutator callback - deletes a byte sequence in the input.527 */528 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDelete(PRTFUZZCTXINT pThis, const void *pvBuf, size_t cbBuf, PPRTFUZZINPUTINT ppInputMutated)529 {530 int rc = VINF_SUCCESS;531 if (cbBuf > 1)532 {533 size_t cbInputMutated = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)cbBuf - 1);534 size_t cbDel = cbBuf - cbInputMutated;535 uint32_t offDel = RTRandAdvU32Ex(pThis->hRand, 0, (uint32_t)(cbBuf - cbDel));536 uint8_t *pbBuf = (uint8_t *)pvBuf;537 538 PRTFUZZINPUTINT pInputMutated = rtFuzzCtxInputCreate(pThis, cbInputMutated);539 if (RT_LIKELY(pInputMutated))540 {541 if (offDel)542 memcpy(&pInputMutated->abInput[0], pbBuf, offDel);543 memcpy(&pInputMutated->abInput[offDel], &pbBuf[offDel + cbDel], cbBuf - offDel - cbDel);544 RTMd5(&pInputMutated->abInput[0], pInputMutated->cbInput, &pInputMutated->abMd5Hash[0]);545 *ppInputMutated = pInputMutated;546 }547 else548 rc = VERR_NO_MEMORY;549 }550 551 return rc;552 }553 554 555 static PRTFUZZCTXINT rtFuzzCtxCreateEmpty(void)556 {557 PRTFUZZCTXINT pThis = (PRTFUZZCTXINT)RTMemAllocZ(sizeof(*pThis));558 if (RT_LIKELY(pThis))559 {560 pThis->u32Magic = RTFUZZCTX_MAGIC;561 pThis->cRefs = 1;562 pThis->TreeSeedsHigh = NULL;563 pThis->cbInputMax = UINT32_MAX;564 pThis->cInputs = 0;565 pThis->fFlagsBehavioral = 0;566 RTListInit(&pThis->LstInputs);567 568 int rc = RTRandAdvCreateParkMiller(&pThis->hRand);569 if (RT_SUCCESS(rc))570 {571 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS());572 return pThis;573 }574 742 575 743 RTMemFree(pThis); 576 }577 578 return NULL;579 }580 581 582 RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx)583 {584 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER);585 586 int rc = VINF_SUCCESS;587 PRTFUZZCTXINT pThis = rtFuzzCtxCreateEmpty();588 if (RT_LIKELY(pThis))589 {590 *phFuzzCtx = pThis;591 return VINF_SUCCESS;592 744 } 593 745 else … … 595 747 596 748 return rc; 749 } 750 751 752 /** 753 * Destroys the given fuzzing input. 754 * 755 * @returns nothing. 756 * @param pThis The fuzzing input to destroy. 757 */ 758 static void rtFuzzInputDestroy(PRTFUZZINPUTINT pThis) 759 { 760 PRTFUZZCTXINT pFuzzer = pThis->pFuzzer; 761 762 if ( pFuzzer->enmType == RTFUZZCTXTYPE_BLOB 763 && pThis->u.Blob.pvInput) 764 rtFuzzCtxMemoryFree(pFuzzer, pThis->u.Blob.pvInput); 765 766 rtFuzzCtxMemoryFree(pFuzzer, pThis); 767 RTFuzzCtxRelease(pFuzzer); 768 } 769 770 771 /** 772 * Creates the final input data applying all accumulated mutations. 773 * 774 * @returns IPRT status code. 775 * @param pThis The fuzzing input to finalize. 776 */ 777 static int rtFuzzInputDataFinalize(PRTFUZZINPUTINT pThis) 778 { 779 Assert(!pThis->u.Blob.pvInput); 780 781 int rc = VINF_SUCCESS; 782 uint8_t *pbBuf = (uint8_t *)rtFuzzCtxMemoryAlloc(pThis->pFuzzer, pThis->u.Blob.cbAlloc); 783 if (RT_LIKELY(pbBuf)) 784 { 785 pThis->u.Blob.pvInput = pbBuf; 786 pThis->u.Blob.cbInput = pThis->pMutationTop->cbInput; 787 788 size_t cbInputNow = pThis->apMutations[0]->cbInput; 789 for (uint32_t i = 0; i < pThis->pMutationTop->iLvl + 1; i++) 790 { 791 PCRTFUZZMUTATION pMutation = pThis->apMutations[i]; 792 pMutation->pMutator->pfnExec(pThis->pFuzzer, pMutation, pbBuf + pMutation->offMutation, 793 cbInputNow - pMutation->offMutation); 794 795 cbInputNow = pMutation->cbInput; 796 } 797 798 Assert(cbInputNow == pThis->u.Blob.cbInput); 799 } 800 else 801 rc = VERR_NO_MEMORY; 802 803 return rc; 804 } 805 806 807 RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx, RTFUZZCTXTYPE enmType) 808 { 809 AssertPtrReturn(phFuzzCtx, VERR_INVALID_POINTER); 810 811 return rtFuzzCtxCreateEmpty(phFuzzCtx, enmType); 597 812 } 598 813 … … 604 819 AssertReturn(cbState > 0, VERR_INVALID_PARAMETER); 605 820 821 #if 0 606 822 int rc = VINF_SUCCESS; 607 823 if (cbState >= sizeof(RTFUZZCTXSTATE)) … … 679 895 680 896 return rc; 897 #else 898 return VERR_NOT_IMPLEMENTED; 899 #endif 681 900 } 682 901 … … 734 953 AssertPtrReturn(pcbState, VERR_INVALID_POINTER); 735 954 955 #if 0 736 956 char aszPrngExport[_4K]; /* Should be plenty of room here. */ 737 957 size_t cbPrng = sizeof(aszPrngExport); … … 799 1019 800 1020 return rc; 1021 #else 1022 return VERR_NOT_IMPLEMENTED; 1023 #endif 801 1024 } 802 1025 … … 838 1061 AssertReturn(cbInput, VERR_INVALID_POINTER); 839 1062 840 /* Generate MD5 checksum and try to locate input. */841 1063 int rc = VINF_SUCCESS; 842 uint8_t abDigest[RTMD5_HASH_SIZE]; 843 RTMd5(pvInput, cbInput, &abDigest[0]); 844 845 PRTFUZZINPUTINT pInput = rtFuzzCtxInputLocate(pThis, &abDigest[0], true /*fExact*/, NULL /*ppIntermediate*/); 846 if (!pInput) 847 { 848 pInput = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbInput])); 849 if (RT_LIKELY(pInput)) 850 { 851 pInput->cRefs = 1; 852 pInput->pFuzzer = pThis; 853 pInput->cbInput = cbInput; 854 memcpy(&pInput->abInput[0], pvInput, cbInput); 855 memcpy(&pInput->abMd5Hash[0], &abDigest[0], sizeof(abDigest)); 856 rc = rtFuzzCtxInputAdd(pThis, pInput); 857 if (RT_FAILURE(rc)) 858 RTMemFree(pInput); 859 } 860 else 861 rc = VERR_NO_MEMORY; 1064 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbInput); 1065 if (RT_LIKELY(pMutation)) 1066 { 1067 pMutation->pMutator = &g_MutatorCorpus; 1068 pMutation->cbInput = cbInput; 1069 memcpy(&pMutation->u.abCorpus[0], pvInput, cbInput); 1070 rc = rtFuzzCtxMutationAdd(pThis, pMutation); 1071 if (RT_FAILURE(rc)) 1072 rtFuzzMutationDestroy(pMutation); 862 1073 } 863 1074 else 864 rc = VERR_ ALREADY_EXISTS;1075 rc = VERR_NO_MEMORY; 865 1076 866 1077 return rc; … … 897 1108 if (RT_SUCCESS(rc)) 898 1109 { 899 PRTFUZZ INPUTINT pInput = (PRTFUZZINPUTINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTFUZZINPUTINT, abInput[cbFile]));900 if (RT_LIKELY(p Input))1110 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, 0, NULL, cbFile); 1111 if (RT_LIKELY(pMutation)) 901 1112 { 902 pInput->cRefs = 1; 903 pInput->pFuzzer = pThis; 904 pInput->cbInput = cbFile; 905 906 rc = RTVfsFileRead(hVfsFile, &pInput->abInput[0], cbFile, NULL); 1113 pMutation->pMutator = &g_MutatorCorpus; 1114 pMutation->cbInput = cbFile; 1115 rc = RTVfsFileRead(hVfsFile, &pMutation->u.abCorpus[0], cbFile, NULL); 907 1116 if (RT_SUCCESS(rc)) 908 { 909 /* Generate MD5 checksum and try to locate input. */ 910 uint8_t abDigest[RTMD5_HASH_SIZE]; 911 RTMd5(&pInput->abInput[0], cbFile, &abDigest[0]); 912 913 if (!rtFuzzCtxInputLocate(pThis, &abDigest[0], true /*fExact*/, NULL /*ppIntermediate*/)) 914 { 915 memcpy(&pInput->abMd5Hash[0], &abDigest[0], sizeof(abDigest)); 916 rc = rtFuzzCtxInputAdd(pThis, pInput); 917 } 918 else 919 rc = VERR_ALREADY_EXISTS; 920 } 1117 rc = rtFuzzCtxMutationAdd(pThis, pMutation); 921 1118 922 1119 if (RT_FAILURE(rc)) 923 RTMemFree(pInput);1120 rtFuzzMutationDestroy(pMutation); 924 1121 } 925 else926 rc = VERR_NO_MEMORY;927 1122 } 928 1123 … … 1059 1254 1060 1255 uint32_t cTries = 0; 1061 PRTFUZZ INPUTINT pSrc = rtFuzzCtxInputPickRnd(pThis);1256 PRTFUZZMUTATION pMutationParent = rtFuzzCtxMutationPickRnd(pThis); 1062 1257 do 1063 1258 { 1064 RTFUZZCTXMUTATOR enmMutator = (RTFUZZCTXMUTATOR)RTRandAdvU32Ex(pThis->hRand, 1, RTFUZZCTXMUTATOR_LAST); 1065 PRTFUZZINPUTINT pInput = NULL; 1066 rc = g_apfnMutators[enmMutator](pThis, &pSrc->abInput[0], pSrc->cbInput, &pInput); 1259 uint32_t idxMutator = RTRandAdvU32Ex(pThis->hRand, 0, pThis->cMutators - 1); 1260 PCRTFUZZMUTATOR pMutator = &pThis->paMutators[idxMutator]; 1261 PRTFUZZMUTATION pMutation = NULL; 1262 1263 uint64_t offStart = 0; 1264 if (!(pMutator->fFlags & RTFUZZMUTATOR_F_END_OF_BUF)) 1265 offStart = RTRandAdvU64Ex(pThis->hRand, 0, pMutationParent->cbInput); 1266 else 1267 offStart = pMutationParent->cbInput; 1268 1269 rc = pMutator->pfnPrep(pThis, offStart, pMutationParent, &pMutation); 1067 1270 if ( RT_SUCCESS(rc) 1068 && VALID_PTR(p Input))1271 && VALID_PTR(pMutation)) 1069 1272 { 1273 pMutation->pMutator = pMutator; 1274 1070 1275 if (pThis->fFlagsBehavioral & RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS) 1071 rtFuzzCtxInputAdd(pThis, pInput); 1072 *phFuzzInput = pInput; 1073 return rc; 1276 rtFuzzCtxMutationAdd(pThis, pMutation); 1277 1278 /* Create a new input. */ 1279 PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)rtFuzzCtxMemoryAlloc(pThis, RT_UOFFSETOF_DYN(RTFUZZINPUTINT, apMutations[pMutation->iLvl + 1])); 1280 if (RT_LIKELY(pInput)) 1281 { 1282 pInput->u32Magic = 0; /** @todo */ 1283 pInput->cRefs = 1; 1284 pInput->pFuzzer = pThis; 1285 pInput->pMutationTop = pMutation; 1286 RTFuzzCtxRetain(pThis); 1287 1288 /* Traverse the mutations top to bottom and insert into the array. */ 1289 uint32_t idx = pMutation->iLvl + 1; 1290 PCRTFUZZMUTATION pMutationCur = pMutation; 1291 size_t cbAlloc = 0; 1292 while (idx > 0) 1293 { 1294 pInput->apMutations[idx - 1] = pMutationCur; 1295 cbAlloc = RT_MAX(cbAlloc, pMutationCur->cbInput); 1296 pMutationCur = pMutationCur->pMutationParent; 1297 idx--; 1298 } 1299 1300 pInput->u.Blob.cbAlloc = cbAlloc; 1301 *phFuzzInput = pInput; 1302 return rc; 1303 } 1304 else 1305 rc = VERR_NO_MEMORY; 1074 1306 } 1075 1307 } while (++cTries <= 50); … … 1082 1314 1083 1315 1084 RTDECL(int) RTFuzzCtxMutateBuffer(RTFUZZCTX hFuzzCtx, void *pvBuf, size_t cbBuf, PRTFUZZINPUT phFuzzInput) 1085 { 1316 RTDECL(int) RTFuzzInputQueryBlobData(RTFUZZINPUT hFuzzInput, void **ppv, size_t *pcb) 1317 { 1318 PRTFUZZINPUTINT pThis = hFuzzInput; 1319 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1320 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE); 1321 1086 1322 int rc = VINF_SUCCESS; 1087 PRTFUZZCTXINT pThis = hFuzzCtx; 1088 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1089 AssertPtrReturn(phFuzzInput, VERR_INVALID_POINTER); 1090 1091 uint32_t cTries = 0; 1092 do 1093 { 1094 RTFUZZCTXMUTATOR enmMutator = (RTFUZZCTXMUTATOR)RTRandAdvU32Ex(pThis->hRand, 1, RTFUZZCTXMUTATOR_LAST); 1095 PRTFUZZINPUTINT pInput = NULL; 1096 rc = g_apfnMutators[enmMutator](pThis, pvBuf, cbBuf, &pInput); 1097 if ( RT_SUCCESS(rc) 1098 && VALID_PTR(pInput)) 1099 { 1100 *phFuzzInput = pInput; 1101 return rc; 1102 } 1103 } while (++cTries <= 50); 1323 if (!pThis->u.Blob.pvInput) 1324 rc = rtFuzzInputDataFinalize(pThis); 1104 1325 1105 1326 if (RT_SUCCESS(rc)) 1106 rc = VERR_INVALID_STATE; 1107 1108 return rc; 1327 { 1328 AssertPtr(pThis->u.Blob.pvInput); 1329 Assert(pThis->u.Blob.cbInput > 0); 1330 1331 *ppv = pThis->u.Blob.pvInput; 1332 *pcb = pThis->u.Blob.cbInput; 1333 } 1334 1335 return rc; 1336 } 1337 1338 1339 RTDECL(int) RTFuzzInputMutateStreamData(RTFUZZINPUT hFuzzInput, void *pvBuf, size_t cbBuf) 1340 { 1341 PRTFUZZINPUTINT pThis = hFuzzInput; 1342 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1343 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_STREAM, VERR_INVALID_STATE); 1344 1345 RT_NOREF(pvBuf, cbBuf); 1346 return VERR_NOT_IMPLEMENTED; 1109 1347 } 1110 1348 … … 1137 1375 1138 1376 1139 RTDECL(int) RTFuzzInputQueryData(RTFUZZINPUT hFuzzInput, void **ppv, size_t *pcb)1140 {1141 PRTFUZZINPUTINT pThis = hFuzzInput;1142 AssertPtrReturn(pThis, VERR_INVALID_POINTER);1143 AssertPtrReturn(ppv, VERR_INVALID_POINTER);1144 AssertPtrReturn(pcb, VERR_INVALID_POINTER);1145 1146 *ppv = &pThis->abInput[0];1147 *pcb = pThis->cbInput;1148 return VINF_SUCCESS;1149 }1150 1151 1152 1377 RTDECL(int) RTFuzzInputQueryDigestString(RTFUZZINPUT hFuzzInput, char *pszDigest, size_t cchDigest) 1153 1378 { 1154 1379 PRTFUZZINPUTINT pThis = hFuzzInput; 1155 1380 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1381 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE); 1156 1382 AssertPtrReturn(pszDigest, VERR_INVALID_POINTER); 1157 1383 AssertReturn(cchDigest >= RTMD5_STRING_LEN + 1, VERR_INVALID_PARAMETER); 1158 1384 1159 return RTMd5ToString(&pThis->abMd5Hash[0], pszDigest, cchDigest); 1385 int rc = VINF_SUCCESS; 1386 if (!pThis->u.Blob.pvInput) 1387 rc = rtFuzzInputDataFinalize(pThis); 1388 1389 if (RT_SUCCESS(rc)) 1390 { 1391 uint8_t abHash[RTMD5_HASH_SIZE]; 1392 RTMd5(pThis->u.Blob.pvInput, pThis->u.Blob.cbInput, &abHash[0]); 1393 rc = RTMd5ToString(&abHash[0], pszDigest, cchDigest); 1394 } 1395 1396 return rc; 1160 1397 } 1161 1398 … … 1165 1402 PRTFUZZINPUTINT pThis = hFuzzInput; 1166 1403 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1404 AssertReturn(pThis->pFuzzer->enmType == RTFUZZCTXTYPE_BLOB, VERR_INVALID_STATE); 1167 1405 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 1168 1406 1169 RTFILE hFile; 1170 int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1407 int rc = VINF_SUCCESS; 1408 if (!pThis->u.Blob.pvInput) 1409 rc = rtFuzzInputDataFinalize(pThis); 1410 1171 1411 if (RT_SUCCESS(rc)) 1172 1412 { 1173 rc = RTFileWrite(hFile, &pThis->abInput[0], pThis->cbInput, NULL); 1174 AssertRC(rc); 1175 RTFileClose(hFile); 1176 1177 if (RT_FAILURE(rc)) 1178 RTFileDelete(pszFilename); 1413 RTFILE hFile; 1414 rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1415 if (RT_SUCCESS(rc)) 1416 { 1417 rc = RTFileWrite(hFile, pThis->u.Blob.pvInput, pThis->u.Blob.cbInput, NULL); 1418 AssertRC(rc); 1419 RTFileClose(hFile); 1420 1421 if (RT_FAILURE(rc)) 1422 RTFileDelete(pszFilename); 1423 } 1179 1424 } 1180 1425 … … 1188 1433 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1189 1434 1190 return rtFuzzCtx InputAdd(pThis->pFuzzer, pThis);1435 return rtFuzzCtxMutationAdd(pThis->pFuzzer, pThis->pMutationTop); 1191 1436 } 1192 1437 … … 1197 1442 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1198 1443 1444 #if 0 1199 1445 int rc = VINF_SUCCESS; 1200 1446 PRTFUZZINTERMEDIATE pIntermediate = NULL; … … 1212 1458 else 1213 1459 rc = VERR_NOT_FOUND; 1214 1215 return rc; 1216 } 1217 1460 #endif 1461 1462 return VERR_NOT_IMPLEMENTED; 1463 } 1464 -
trunk/src/VBox/Runtime/common/fuzz/fuzzclientcmd.cpp
r76553 r77482 85 85 void *pv = NULL; 86 86 size_t cb = 0; 87 rc = RTFuzzInputQuery Data(hFuzzInput, &pv, &cb);87 rc = RTFuzzInputQueryBlobData(hFuzzInput, &pv, &cb); 88 88 if (RT_SUCCESS(rc)) 89 89 { -
trunk/src/VBox/Runtime/common/fuzz/fuzzmastercmd.cpp
r76553 r77482 637 637 if (RT_LIKELY(pFuzzRun->pszId)) 638 638 { 639 rc = RTFuzzObsCreate(&pFuzzRun->hFuzzObs );639 rc = RTFuzzObsCreate(&pFuzzRun->hFuzzObs, RTFUZZCTXTYPE_BLOB); 640 640 if (RT_SUCCESS(rc)) 641 641 {
Note:
See TracChangeset
for help on using the changeset viewer.