Changeset 77650 in vbox
- Timestamp:
- Mar 11, 2019 12:48:14 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp
r77564 r77650 35 35 #include <iprt/assert.h> 36 36 #include <iprt/avl.h> 37 #include <iprt/critsect.h> 37 38 #include <iprt/ctype.h> 38 39 #include <iprt/dir.h> … … 67 68 68 69 /** 70 * Mutator class. 71 */ 72 typedef 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 /** 69 90 * Mutator preparation callback. 70 91 * … … 140 161 /** Mutator index. */ 141 162 uint32_t uMutator; 163 /** Mutator class. */ 164 RTFUZZMUTATORCLASS enmClass; 142 165 /** Additional flags for the mutator, controlling the behavior. */ 143 166 uint64_t fFlags; … … 172 195 /** The AVL tree core. */ 173 196 AVLU64NODECORE Core; 197 /** The list node if the mutation has the mutated 198 * data allocated. */ 199 RTLISTNODE NdAlloc; 174 200 /** Magic identifying this structure. */ 175 201 uint32_t u32Magic; … … 178 204 /** The fuzzer this mutation belongs to. */ 179 205 PRTFUZZCTXINT pFuzzer; 180 /** Parent mutation ( reference is held), NULL means root or original data. */181 P CRTFUZZMUTATIONpMutationParent;206 /** Parent mutation (no reference is held), NULL means root or original data. */ 207 PRTFUZZMUTATION pMutationParent; 182 208 /** Mutation level. */ 183 209 uint32_t iLvl; … … 190 216 /** Size of the mutation dependent data. */ 191 217 size_t cbMutation; 218 /** Size allocated for the input. */ 219 size_t cbAlloc; 220 /** Pointer to the input data if created. */ 221 void *pvInput; 192 222 /** Flag whether the mutation is contained in the tree of the context. */ 193 223 bool fInTree; 224 /** Flag whether the mutation input data is cached. */ 225 bool fCached; 194 226 /** Mutation dependent data, variable in size. */ 195 227 uint8_t abMutation[1]; … … 216 248 struct 217 249 { 218 /** Size to allocate initially. */219 size_t cbAlloc;220 /** Input data size. */221 size_t cbInput;222 250 /** Pointer to the input data if created. */ 223 251 void *pvInput; … … 230 258 } Stream; 231 259 } u; 232 /** Array holding all the individual mutations, variable in size. */233 PCRTFUZZMUTATION apMutations[1];234 260 } RTFUZZINPUTINT; 235 261 /** Pointer to the internal input state. */ … … 266 292 /** Pointer to the mutator descriptors. */ 267 293 PRTFUZZMUTATOR paMutators; 294 /** Maximum amount of bytes of mutated inputs to cache. */ 295 size_t cbMutationsAllocMax; 296 /** Current amount of bytes of cached mutated inputs. */ 297 size_t cbMutationsAlloc; 298 /** List of mutators having data allocated currently. */ 299 RTLISTANCHOR LstMutationsAlloc; 300 /** Critical section protecting the allocation list. */ 301 RTCRITSECT CritSectAlloc; 268 302 /** Total number of bytes of memory currently allocated in total for this context. */ 269 303 volatile size_t cbMemTotal; … … 361 395 362 396 397 /** 398 * Integer replacing mutator additional data. 399 */ 400 typedef struct RTFUZZMUTATORINTEGER 401 { 402 /** The integer class. */ 403 uint8_t uIntClass; 404 /** Flag whether to do a byte swap. */ 405 bool fByteSwap; 406 /** The index into the class specific array. */ 407 uint16_t idxInt; 408 } RTFUZZMUTATORINTEGER; 409 /** Pointer to additional integer replacing mutator data. */ 410 typedef RTFUZZMUTATORINTEGER *PRTFUZZMUTATORINTEGER; 411 /** Pointer to constant additional integer replacing mutator data. */ 412 typedef const RTFUZZMUTATORINTEGER *PCRTFUZZMUTATORINTEGER; 413 363 414 /********************************************************************************************************************************* 364 415 * Internal Functions * … … 376 427 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeletePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 377 428 PPRTFUZZMUTATION ppMutation); 429 static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 430 PPRTFUZZMUTATION ppMutation); 431 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 432 PPRTFUZZMUTATION ppMutation); 378 433 379 434 static DECLCALLBACK(int) rtFuzzCtxMutatorCorpusExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, … … 391 446 static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceDeleteExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, 392 447 uint8_t *pbBuf, size_t cbBuf); 448 static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, 449 uint8_t *pbBuf, size_t cbBuf); 450 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, 451 uint8_t *pbBuf, size_t cbBuf); 393 452 394 453 static DECLCALLBACK(int) rtFuzzCtxMutatorExportDefault(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, … … 397 456 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser); 398 457 458 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, 459 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser); 460 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverImport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation, 461 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser); 462 399 463 400 464 /********************************************************************************************************************************* 401 465 * Global Variables * 402 466 *********************************************************************************************************************************/ 467 468 /** Signed 8bit interesting values. */ 469 static int8_t s_ai8Interesting[] = { INT8_MIN, INT8_MIN + 1, -1, 0, 1, INT8_MAX - 1, INT8_MAX }; 470 /** Unsigned 8bit interesting values. */ 471 static uint8_t s_au8Interesting[] = { 0, 1, UINT8_MAX - 1, UINT8_MAX }; 472 /** Signed 16bit interesting values. */ 473 static int16_t s_ai16Interesting[] = { INT16_MIN, INT16_MIN + 1, -1, 0, 1, INT16_MAX - 1, INT16_MAX }; 474 /** Unsigned 16bit interesting values. */ 475 static uint16_t s_au16Interesting[] = { 0, 1, UINT16_MAX - 1, UINT16_MAX }; 476 /** Signed 32bit interesting values. */ 477 static int32_t s_ai32Interesting[] = { INT32_MIN, INT32_MIN + 1, -1, 0, 1, INT32_MAX - 1, INT32_MAX }; 478 /** Unsigned 32bit interesting values. */ 479 static uint32_t s_au32Interesting[] = { 0, 1, UINT32_MAX - 1, UINT32_MAX }; 480 /** Signed 64bit interesting values. */ 481 static int64_t s_ai64Interesting[] = { INT64_MIN, INT64_MIN + 1, -1, 0, 1, INT64_MAX - 1, INT64_MAX }; 482 /** Unsigned 64bit interesting values. */ 483 static uint64_t s_au64Interesting[] = { 0, 1, UINT64_MAX - 1, UINT64_MAX }; 484 485 403 486 /** 404 487 * The special corpus mutator for the original data. … … 412 495 /** uMutator. */ 413 496 RTFUZZMUTATOR_ID_CORPUS, 497 /** enmClass. */ 498 RTFUZZMUTATORCLASS_BYTES, 414 499 /** fFlags */ 415 500 RTFUZZMUTATOR_F_DEFAULT, … … 429 514 static RTFUZZMUTATOR const g_aMutators[] = 430 515 { 431 /* pszId pszDesc uMutator fFlags pfnPrep pfnExec pfnExport pfnImport */ 432 { "BitFlip", "Flips a single bit in the input", 0, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorBitFlipPrep, rtFuzzCtxMutatorBitFlipExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 433 { "ByteReplace", "Replaces a single byte in the input", 1, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteReplacePrep, rtFuzzCtxMutatorByteReplaceExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 434 { "ByteInsert", "Inserts a single byte sequence into the input", 2, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteInsertPrep, rtFuzzCtxMutatorByteInsertExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 435 { "ByteSeqIns", "Inserts a byte sequence in the input", 3, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 436 { "ByteSeqApp", "Appends a byte sequence to the input", 4, RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 437 { "ByteDelete", "Deletes a single byte sequence from the input", 5, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteDeletePrep, rtFuzzCtxMutatorByteDeleteExec, NULL, NULL }, 438 { "ByteSeqDel", "Deletes a byte sequence from the input", 6, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceDeletePrep, rtFuzzCtxMutatorByteSequenceDeleteExec, NULL, NULL } 516 /* pszId pszDesc uMutator enmClass fFlags pfnPrep pfnExec pfnExport pfnImport */ 517 { "BitFlip", "Flips a single bit in the input", 0, RTFUZZMUTATORCLASS_BITS, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorBitFlipPrep, rtFuzzCtxMutatorBitFlipExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 518 { "ByteReplace", "Replaces a single byte in the input", 1, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteReplacePrep, rtFuzzCtxMutatorByteReplaceExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 519 { "ByteInsert", "Inserts a single byte sequence into the input", 2, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteInsertPrep, rtFuzzCtxMutatorByteInsertExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 520 { "ByteSeqIns", "Inserts a byte sequence in the input", 3, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 521 { "ByteSeqApp", "Appends a byte sequence to the input", 4, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 522 { "ByteDelete", "Deletes a single byte sequence from the input", 5, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteDeletePrep, rtFuzzCtxMutatorByteDeleteExec, NULL, NULL }, 523 { "ByteSeqDel", "Deletes a byte sequence from the input", 6, RTFUZZMUTATORCLASS_BYTES, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorByteSequenceDeletePrep, rtFuzzCtxMutatorByteSequenceDeleteExec, NULL, NULL }, 524 { "IntReplace", "Replaces a possible integer with an interesting one", 7, RTFUZZMUTATORCLASS_INTEGERS, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorIntegerReplacePrep, rtFuzzCtxMutatorIntegerReplaceExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault }, 525 { "MutCrossover", "Creates a crossover of two other mutations", 8, RTFUZZMUTATORCLASS_MUTATORS, RTFUZZMUTATOR_F_DEFAULT, rtFuzzCtxMutatorCrossoverPrep, rtFuzzCtxMutatorCrossoverExec, rtFuzzCtxMutatorCrossoverExport, rtFuzzCtxMutatorCrossoverImport } 439 526 }; 440 527 … … 449 536 static void *rtFuzzCtxMemoryAlloc(PRTFUZZCTXINT pThis, size_t cb) 450 537 { 538 AssertReturn(cb > 0, NULL); 539 451 540 PRTFUZZMEMHDR pMemHdr = (PRTFUZZMEMHDR)RTMemAllocZ(cb + sizeof(RTFUZZMEMHDR)); 452 541 if (RT_LIKELY(pMemHdr)) … … 478 567 479 568 /** 569 * Frees the cached inputs until the given amount is free. 570 * 571 * @returns Whether the amount of memory is free. 572 * @param pThis The fuzzer context instance. 573 * @param cb How many bytes to reclaim 574 */ 575 static bool rtFuzzCtxMutationAllocReclaim(PRTFUZZCTXINT pThis, size_t cb) 576 { 577 while ( !RTListIsEmpty(&pThis->LstMutationsAlloc) 578 && pThis->cbMutationsAlloc + cb > pThis->cbMutationsAllocMax) 579 { 580 PRTFUZZMUTATION pMutation = RTListGetLast(&pThis->LstMutationsAlloc, RTFUZZMUTATION, NdAlloc); 581 AssertPtr(pMutation); 582 AssertPtr(pMutation->pvInput); 583 584 rtFuzzCtxMemoryFree(pThis, pMutation->pvInput); 585 pThis->cbMutationsAlloc -= pMutation->cbAlloc; 586 pMutation->pvInput = NULL; 587 pMutation->cbAlloc = 0; 588 pMutation->fCached = false; 589 RTListNodeRemove(&pMutation->NdAlloc); 590 } 591 592 return pThis->cbMutationsAlloc + cb <= pThis->cbMutationsAllocMax; 593 } 594 595 596 /** 597 * Updates the cache status of the given mutation. 598 * 599 * @returns nothing. 600 * @param pThis The fuzzer context instance. 601 * @param pMutation The mutation to update. 602 */ 603 static void rtFuzzCtxMutationMaybeEnterCache(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation) 604 { 605 RTCritSectEnter(&pThis->CritSectAlloc); 606 607 /* Initial corpus mutations are not freed. */ 608 if ( pMutation->pvInput 609 && pMutation->pMutator != &g_MutatorCorpus) 610 { 611 Assert(!pMutation->fCached); 612 613 if (rtFuzzCtxMutationAllocReclaim(pThis, pMutation->cbAlloc)) 614 { 615 RTListPrepend(&pThis->LstMutationsAlloc, &pMutation->NdAlloc); 616 pThis->cbMutationsAlloc += pMutation->cbAlloc; 617 pMutation->fCached = true; 618 } 619 else 620 { 621 rtFuzzCtxMemoryFree(pThis, pMutation->pvInput); 622 pMutation->pvInput = NULL; 623 pMutation->cbAlloc = 0; 624 pMutation->fCached = false; 625 } 626 } 627 RTCritSectLeave(&pThis->CritSectAlloc); 628 } 629 630 631 /** 632 * Removes a cached mutation from the cache. 633 * 634 * @returns nothing. 635 * @param pThis The fuzzer context instance. 636 * @param pMutation The mutation to remove. 637 */ 638 static void rtFuzzCtxMutationCacheRemove(PRTFUZZCTXINT pThis, PRTFUZZMUTATION pMutation) 639 { 640 RTCritSectEnter(&pThis->CritSectAlloc); 641 if (pMutation->fCached) 642 { 643 RTListNodeRemove(&pMutation->NdAlloc); 644 pThis->cbMutationsAlloc -= pMutation->cbAlloc; 645 pMutation->fCached = false; 646 } 647 RTCritSectLeave(&pThis->CritSectAlloc); 648 } 649 650 651 /** 480 652 * Destroys the given mutation. 481 653 * … … 485 657 static void rtFuzzMutationDestroy(PRTFUZZMUTATION pMutation) 486 658 { 659 if (pMutation->pvInput) 660 { 661 rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation->pvInput); 662 if (pMutation->fCached) 663 { 664 RTCritSectEnter(&pMutation->pFuzzer->CritSectAlloc); 665 RTListNodeRemove(&pMutation->NdAlloc); 666 pMutation->pFuzzer->cbMutationsAlloc -= pMutation->cbAlloc; 667 RTCritSectLeave(&pMutation->pFuzzer->CritSectAlloc); 668 } 669 pMutation->pvInput = NULL; 670 pMutation->cbAlloc = 0; 671 pMutation->fCached = false; 672 } 487 673 rtFuzzCtxMemoryFree(pMutation->pFuzzer, pMutation); 488 674 } … … 501 687 || pMutation->fInTree) 502 688 && cRefs < _1M, ("%#x %p\n", cRefs, pMutation)); 689 690 if (cRefs == 1) 691 rtFuzzCtxMutationCacheRemove(pMutation->pFuzzer, pMutation); 503 692 return cRefs; 504 693 } … … 515 704 uint32_t cRefs = ASMAtomicDecU32(&pMutation->cRefs); 516 705 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pMutation)); 517 if (cRefs == 0 && !pMutation->fInTree) 518 rtFuzzMutationDestroy(pMutation); 706 707 if (cRefs == 0) 708 { 709 rtFuzzCtxMutationMaybeEnterCache(pMutation->pFuzzer, pMutation); 710 711 if (!pMutation->fInTree) 712 rtFuzzMutationDestroy(pMutation); 713 } 714 519 715 return cRefs; 520 716 } … … 546 742 547 743 /** 548 * Returns a random mutation from the corpus of the given fuzzer context.549 * 550 * @returns Pointer to a randomly picked mutation (reference count is increased).744 * Locates the mutation with the given key. 745 * 746 * @returns Pointer to the mutation if found or NULL otherwise. 551 747 * @param pThis The fuzzer context instance. 552 */ 553 static PRTFUZZMUTATION rtFuzzCtxMutationPickRnd(PRTFUZZCTXINT pThis) 554 { 555 uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 1, ASMAtomicReadU64(&pThis->cMutations)); 556 748 * @param uKey The key to locate. 749 */ 750 static PRTFUZZMUTATION rtFuzzCtxMutationLocate(PRTFUZZCTXINT pThis, uint64_t uKey) 751 { 557 752 int rc = RTSemRWRequestRead(pThis->hSemRwMutations, RT_INDEFINITE_WAIT); 558 753 AssertRC(rc); RT_NOREF(rc); … … 562 757 * already but the mutation is not yet in the tree. 563 758 */ 564 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)RTAvlU64GetBestFit(&pThis->TreeMutations, idxMutation, false /*fAbove*/); 565 AssertPtr(pMutation); 566 567 /* Increase reference count of the mutation. */ 568 rtFuzzMutationRetain(pMutation); 759 PRTFUZZMUTATION pMutation = (PRTFUZZMUTATION)RTAvlU64GetBestFit(&pThis->TreeMutations, uKey, false /*fAbove*/); 760 if (RT_LIKELY(pMutation)) 761 rtFuzzMutationRetain(pMutation); 762 569 763 rc = RTSemRWReleaseRead(pThis->hSemRwMutations); 570 764 AssertRC(rc); RT_NOREF(rc); 571 765 572 766 return pMutation; 767 } 768 769 770 /** 771 * Returns a random mutation from the corpus of the given fuzzer context. 772 * 773 * @returns Pointer to a randomly picked mutation (reference count is increased). 774 * @param pThis The fuzzer context instance. 775 */ 776 static PRTFUZZMUTATION rtFuzzCtxMutationPickRnd(PRTFUZZCTXINT pThis) 777 { 778 uint64_t idxMutation = RTRandAdvU64Ex(pThis->hRand, 1, ASMAtomicReadU64(&pThis->cMutations)); 779 return rtFuzzCtxMutationLocate(pThis, idxMutation); 573 780 } 574 781 … … 598 805 pMutation->cbMutation = cbAdditional; 599 806 pMutation->fInTree = false; 807 pMutation->fCached = false; 808 pMutation->pvInput = NULL; 809 pMutation->cbInput = 0; 810 pMutation->cbAlloc = 0; 600 811 601 812 if (pMutationParent) … … 610 821 611 822 /** 612 * Dest orys the given fuzzer context freeing all allocated resources.823 * Destroys the given fuzzer context freeing all allocated resources. 613 824 * 614 825 * @returns nothing. … … 618 829 { 619 830 RT_NOREF(pThis); 831 } 832 833 834 /** 835 * Creates the final input data applying all accumulated mutations. 836 * 837 * @returns IPRT status code. 838 * @param pMutation The mutation to finalize. 839 */ 840 static int rtFuzzMutationDataFinalize(PRTFUZZMUTATION pMutation) 841 { 842 if (pMutation->pvInput) 843 return VINF_SUCCESS; 844 845 /* Traverse the mutations top to bottom and insert into the array. */ 846 int rc = VINF_SUCCESS; 847 uint32_t idx = pMutation->iLvl + 1; 848 PRTFUZZMUTATION *papMutations = (PRTFUZZMUTATION *)RTMemTmpAlloc(idx * sizeof(PCRTFUZZMUTATION)); 849 if (RT_LIKELY(papMutations)) 850 { 851 PRTFUZZMUTATION pMutationCur = pMutation; 852 size_t cbAlloc = 0; 853 854 /* 855 * As soon as a mutation with allocated input data is encountered the insertion is 856 * stopped as it contains all necessary mutated inputs we can start from. 857 */ 858 while (idx > 0) 859 { 860 rtFuzzMutationRetain(pMutationCur); 861 papMutations[idx - 1] = pMutationCur; 862 cbAlloc = RT_MAX(cbAlloc, pMutationCur->cbInput); 863 if (pMutationCur->pvInput) 864 { 865 idx--; 866 break; 867 } 868 pMutationCur = pMutationCur->pMutationParent; 869 idx--; 870 } 871 872 pMutation->cbAlloc = cbAlloc; 873 uint8_t *pbBuf = (uint8_t *)rtFuzzCtxMemoryAlloc(pMutation->pFuzzer, cbAlloc); 874 if (RT_LIKELY(pbBuf)) 875 { 876 pMutation->pvInput = pbBuf; 877 878 /* Copy the initial input data. */ 879 size_t cbInputNow = papMutations[idx]->cbInput; 880 memcpy(pbBuf, papMutations[idx]->pvInput, cbInputNow); 881 rtFuzzMutationRelease(papMutations[idx]); 882 883 for (uint32_t i = idx + 1; i < pMutation->iLvl + 1; i++) 884 { 885 PRTFUZZMUTATION pCur = papMutations[i]; 886 pCur->pMutator->pfnExec(pCur->pFuzzer, pCur, (void *)&pCur->abMutation[0], 887 pbBuf + pCur->offMutation, 888 cbInputNow - pCur->offMutation); 889 890 cbInputNow = pCur->cbInput; 891 rtFuzzMutationRelease(pCur); 892 } 893 894 Assert(cbInputNow == pMutation->cbInput); 895 } 896 else 897 rc = VERR_NO_MEMORY; 898 899 RTMemTmpFree(papMutations); 900 } 901 else 902 rc = VERR_NO_MEMORY; 903 904 return rc; 620 905 } 621 906 … … 828 1113 829 1114 830 831 1115 /** 832 1116 * Mutator callback - deletes a byte sequence in the input. … … 868 1152 869 1153 /** 1154 * Mutator callback - replaces a possible integer with something interesting. 1155 */ 1156 static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 1157 PPRTFUZZMUTATION ppMutation) 1158 { 1159 int rc = VINF_SUCCESS; 1160 PRTFUZZMUTATORINTEGER pMutInt = NULL; 1161 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pMutInt), (void **)&pMutInt); 1162 if (RT_LIKELY(pMutation)) 1163 { 1164 size_t cbLeft = pMutationParent->cbInput - offStart; 1165 uint32_t uClassMax = 0; 1166 1167 switch (cbLeft) 1168 { 1169 case 1: 1170 uClassMax = 1; 1171 break; 1172 case 2: 1173 case 3: 1174 uClassMax = 3; 1175 break; 1176 case 4: 1177 case 5: 1178 case 6: 1179 case 7: 1180 uClassMax = 5; 1181 break; 1182 default: 1183 uClassMax = 7; 1184 break; 1185 } 1186 1187 pMutInt->uIntClass = (uint8_t)RTRandAdvU32Ex(pThis->hRand, 0, uClassMax); 1188 pMutInt->fByteSwap = RT_BOOL(RTRandAdvU32Ex(pThis->hRand, 0, 1)); 1189 1190 switch (pMutInt->uIntClass) 1191 { 1192 case 0: 1193 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai8Interesting) - 1); 1194 break; 1195 case 1: 1196 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au8Interesting) - 1); 1197 break; 1198 case 2: 1199 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai16Interesting) - 1); 1200 break; 1201 case 3: 1202 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au16Interesting) - 1); 1203 break; 1204 case 4: 1205 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai32Interesting) - 1); 1206 break; 1207 case 5: 1208 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au32Interesting) - 1); 1209 break; 1210 case 6: 1211 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_ai64Interesting) - 1); 1212 break; 1213 case 7: 1214 pMutInt->idxInt = (uint16_t)RTRandAdvU32Ex(pThis->hRand, 0, RT_ELEMENTS(s_au64Interesting) - 1); 1215 break; 1216 default: 1217 AssertReleaseFailed(); 1218 } 1219 1220 pMutation->cbInput = pMutationParent->cbInput; 1221 *ppMutation = pMutation; 1222 } 1223 else 1224 rc = VERR_NO_MEMORY; 1225 1226 return rc; 1227 } 1228 1229 1230 static DECLCALLBACK(int) rtFuzzCtxMutatorIntegerReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, 1231 uint8_t *pbBuf, size_t cbBuf) 1232 { 1233 RT_NOREF(pThis, pMutation, cbBuf); 1234 union 1235 { 1236 int8_t i8; 1237 uint8_t u8; 1238 int16_t i16; 1239 uint16_t u16; 1240 int32_t i32; 1241 uint32_t u32; 1242 int64_t i64; 1243 uint64_t u64; 1244 } Int; 1245 PCRTFUZZMUTATORINTEGER pMutInt = (PCRTFUZZMUTATORINTEGER)pvMutation; 1246 size_t cb = 0; 1247 1248 switch (pMutInt->uIntClass) 1249 { 1250 case 0: 1251 Int.i8 = s_ai8Interesting[pMutInt->idxInt]; 1252 cb = 1; 1253 break; 1254 case 1: 1255 Int.u8 = s_au8Interesting[pMutInt->idxInt]; 1256 cb = 1; 1257 break; 1258 case 2: 1259 Int.i16 = s_ai16Interesting[pMutInt->idxInt]; 1260 cb = 2; 1261 if (pMutInt->fByteSwap) 1262 Int.u16 = RT_BSWAP_U16(Int.u16); 1263 break; 1264 case 3: 1265 Int.u16 = s_au16Interesting[pMutInt->idxInt]; 1266 cb = 2; 1267 if (pMutInt->fByteSwap) 1268 Int.u16 = RT_BSWAP_U16(Int.u16); 1269 break; 1270 case 4: 1271 Int.i32 = s_ai32Interesting[pMutInt->idxInt]; 1272 cb = 4; 1273 if (pMutInt->fByteSwap) 1274 Int.u32 = RT_BSWAP_U32(Int.u32); 1275 break; 1276 case 5: 1277 Int.u32 = s_au32Interesting[pMutInt->idxInt]; 1278 cb = 4; 1279 if (pMutInt->fByteSwap) 1280 Int.u32 = RT_BSWAP_U32(Int.u32); 1281 break; 1282 case 6: 1283 Int.i64 = s_ai64Interesting[pMutInt->idxInt]; 1284 cb = 8; 1285 if (pMutInt->fByteSwap) 1286 Int.u64 = RT_BSWAP_U64(Int.u64); 1287 break; 1288 case 7: 1289 Int.u64 = s_au64Interesting[pMutInt->idxInt]; 1290 cb = 8; 1291 if (pMutInt->fByteSwap) 1292 Int.u64 = RT_BSWAP_U64(Int.u64); 1293 break; 1294 default: 1295 AssertReleaseFailed(); 1296 } 1297 1298 memcpy(pbBuf, &Int, cb); 1299 return VINF_SUCCESS; 1300 } 1301 1302 1303 /** 1304 * Mutator callback - crosses over two mutations at the given point. 1305 */ 1306 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent, 1307 PPRTFUZZMUTATION ppMutation) 1308 { 1309 int rc = VINF_SUCCESS; 1310 1311 if (pThis->cMutations > 1) 1312 { 1313 uint64_t *pidxMutCrossover = NULL; 1314 PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, sizeof(*pidxMutCrossover), (void **)&pidxMutCrossover); 1315 if (RT_LIKELY(pMutation)) 1316 { 1317 uint32_t cTries = 10; 1318 PRTFUZZMUTATION pMutCrossover = NULL; 1319 /* 1320 * Pick a random mutation to crossover with (making sure it is not the current one 1321 * or the crossover point is beyond the end of input). 1322 */ 1323 do 1324 { 1325 if (pMutCrossover) 1326 rtFuzzMutationRelease(pMutCrossover); 1327 pMutCrossover = rtFuzzCtxMutationPickRnd(pThis); 1328 cTries--; 1329 } while ( ( pMutCrossover == pMutationParent 1330 || offStart >= pMutCrossover->cbInput) 1331 && cTries > 0); 1332 1333 if (cTries) 1334 { 1335 pMutation->cbInput = pMutCrossover->cbInput; 1336 *pidxMutCrossover = pMutCrossover->Core.Key; 1337 *ppMutation = pMutation; 1338 } 1339 else 1340 rtFuzzMutationDestroy(pMutation); 1341 1342 rtFuzzMutationRelease(pMutCrossover); 1343 } 1344 else 1345 rc = VERR_NO_MEMORY; 1346 } 1347 1348 return rc; 1349 } 1350 1351 1352 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, 1353 uint8_t *pbBuf, size_t cbBuf) 1354 { 1355 RT_NOREF(cbBuf); 1356 uint64_t idxMutCrossover = *(uint64_t *)pvMutation; 1357 1358 PRTFUZZMUTATION pMutCrossover = rtFuzzCtxMutationLocate(pThis, idxMutCrossover); 1359 int rc = rtFuzzMutationDataFinalize(pMutCrossover); 1360 if (RT_SUCCESS(rc)) 1361 { 1362 memcpy(pbBuf, (uint8_t *)pMutCrossover->pvInput + pMutation->offMutation, 1363 pMutCrossover->cbInput - pMutation->offMutation); 1364 rtFuzzMutationRelease(pMutCrossover); 1365 } 1366 1367 return rc; 1368 } 1369 1370 1371 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverExport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation, 1372 PFNRTFUZZCTXEXPORT pfnExport, void *pvUser) 1373 { 1374 RT_NOREF(pMutation); 1375 1376 uint64_t idxMutCrossover = *(uint64_t *)pvMutation; 1377 idxMutCrossover = RT_H2LE_U64(idxMutCrossover); 1378 return pfnExport(pThis, &idxMutCrossover, sizeof(idxMutCrossover), pvUser); 1379 } 1380 1381 1382 static DECLCALLBACK(int) rtFuzzCtxMutatorCrossoverImport(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, void *pvMutation, 1383 PFNRTFUZZCTXIMPORT pfnImport, void *pvUser) 1384 { 1385 RT_NOREF(pMutation); 1386 1387 uint64_t uKey = 0; 1388 int rc = pfnImport(pThis, &uKey, sizeof(uKey), NULL, pvUser); 1389 if (RT_SUCCESS(rc)) 1390 { 1391 uKey = RT_LE2H_U64(uKey); 1392 *(uint64_t *)pvMutation = uKey; 1393 } 1394 1395 return rc; 1396 } 1397 1398 1399 /** 870 1400 * Creates an empty fuzzing context. 871 1401 * … … 880 1410 if (RT_LIKELY(pThis)) 881 1411 { 882 pThis->u32Magic = RTFUZZCTX_MAGIC; 883 pThis->cRefs = 1; 884 pThis->enmType = enmType; 885 pThis->TreeMutations = NULL; 886 pThis->cbInputMax = UINT32_MAX; 887 pThis->cMutations = 0; 888 pThis->fFlagsBehavioral = 0; 889 pThis->cbMemTotal = 0; 1412 pThis->u32Magic = RTFUZZCTX_MAGIC; 1413 pThis->cRefs = 1; 1414 pThis->enmType = enmType; 1415 pThis->TreeMutations = NULL; 1416 pThis->cbInputMax = UINT32_MAX; 1417 pThis->cMutations = 0; 1418 pThis->fFlagsBehavioral = 0; 1419 pThis->cbMutationsAllocMax = _1G; 1420 pThis->cbMemTotal = 0; 1421 RTListInit(&pThis->LstMutationsAlloc); 890 1422 891 1423 /* Copy the default mutator descriptors over. */ … … 899 1431 if (RT_SUCCESS(rc)) 900 1432 { 901 rc = RT RandAdvCreateParkMiller(&pThis->hRand);1433 rc = RTCritSectInit(&pThis->CritSectAlloc); 902 1434 if (RT_SUCCESS(rc)) 903 1435 { 904 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS()); 905 *ppThis = pThis; 906 return VINF_SUCCESS; 1436 rc = RTRandAdvCreateParkMiller(&pThis->hRand); 1437 if (RT_SUCCESS(rc)) 1438 { 1439 RTRandAdvSeed(pThis->hRand, RTTimeSystemNanoTS()); 1440 *ppThis = pThis; 1441 return VINF_SUCCESS; 1442 } 1443 1444 RTCritSectDelete(&pThis->CritSectAlloc); 907 1445 } 908 1446 … … 932 1470 PRTFUZZCTXINT pFuzzer = pThis->pFuzzer; 933 1471 934 if ( pFuzzer->enmType == RTFUZZCTXTYPE_BLOB935 && pThis->u.Blob.pvInput)936 rtFuzzCtxMemoryFree(pFuzzer, pThis->u.Blob.pvInput);937 938 1472 rtFuzzMutationRelease(pThis->pMutationTop); 939 1473 rtFuzzCtxMemoryFree(pFuzzer, pThis); 940 1474 RTFuzzCtxRelease(pFuzzer); 941 }942 943 944 /**945 * Creates the final input data applying all accumulated mutations.946 *947 * @returns IPRT status code.948 * @param pThis The fuzzing input to finalize.949 */950 static int rtFuzzInputDataFinalize(PRTFUZZINPUTINT pThis)951 {952 Assert(!pThis->u.Blob.pvInput);953 954 int rc = VINF_SUCCESS;955 uint8_t *pbBuf = (uint8_t *)rtFuzzCtxMemoryAlloc(pThis->pFuzzer, pThis->u.Blob.cbAlloc);956 if (RT_LIKELY(pbBuf))957 {958 pThis->u.Blob.pvInput = pbBuf;959 pThis->u.Blob.cbInput = pThis->pMutationTop->cbInput;960 961 size_t cbInputNow = pThis->apMutations[0]->cbInput;962 for (uint32_t i = 0; i < pThis->pMutationTop->iLvl + 1; i++)963 {964 PCRTFUZZMUTATION pMutation = pThis->apMutations[i];965 pMutation->pMutator->pfnExec(pThis->pFuzzer, pMutation, (void *)&pMutation->abMutation[0],966 pbBuf + pMutation->offMutation,967 cbInputNow - pMutation->offMutation);968 969 cbInputNow = pMutation->cbInput;970 }971 972 Assert(cbInputNow == pThis->u.Blob.cbInput);973 }974 else975 rc = VERR_NO_MEMORY;976 977 return rc;978 1475 } 979 1476 … … 1283 1780 pMutation->pMutator = &g_MutatorCorpus; 1284 1781 pMutation->cbInput = cbInput; 1782 pMutation->pvInput = pvCorpus; 1285 1783 memcpy(pvCorpus, pvInput, cbInput); 1286 1784 rc = rtFuzzCtxMutationAdd(pThis, pMutation); … … 1330 1828 pMutation->pMutator = &g_MutatorCorpus; 1331 1829 pMutation->cbInput = cbFile; 1830 pMutation->pvInput = pvCorpus; 1332 1831 rc = RTVfsFileRead(hVfsFile, pvCorpus, cbFile, NULL); 1333 1832 if (RT_SUCCESS(rc)) … … 1494 1993 1495 1994 /* Create a new input. */ 1496 PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)rtFuzzCtxMemoryAlloc(pThis, RT_UOFFSETOF_DYN(RTFUZZINPUTINT, apMutations[pMutation->iLvl + 1]));1995 PRTFUZZINPUTINT pInput = (PRTFUZZINPUTINT)rtFuzzCtxMemoryAlloc(pThis, sizeof(RTFUZZINPUTINT)); 1497 1996 if (RT_LIKELY(pInput)) 1498 1997 { … … 1503 2002 RTFuzzCtxRetain(pThis); 1504 2003 1505 /* Traverse the mutations top to bottom and insert into the array. */ 1506 uint32_t idx = pMutation->iLvl + 1; 1507 PCRTFUZZMUTATION pMutationCur = pMutation; 1508 size_t cbAlloc = 0; 1509 while (idx > 0) 1510 { 1511 pInput->apMutations[idx - 1] = pMutationCur; 1512 cbAlloc = RT_MAX(cbAlloc, pMutationCur->cbInput); 1513 pMutationCur = pMutationCur->pMutationParent; 1514 idx--; 1515 } 1516 1517 pInput->u.Blob.cbAlloc = cbAlloc; 2004 rtFuzzMutationRelease(pMutationParent); 1518 2005 *phFuzzInput = pInput; 1519 2006 return rc; … … 1524 2011 } while (++cTries <= 50); 1525 2012 2013 rtFuzzMutationRelease(pMutationParent); 1526 2014 if (RT_SUCCESS(rc)) 1527 2015 rc = VERR_INVALID_STATE; … … 1538 2026 1539 2027 int rc = VINF_SUCCESS; 1540 if (!pThis-> u.Blob.pvInput)1541 rc = rtFuzz InputDataFinalize(pThis);2028 if (!pThis->pMutationTop->pvInput) 2029 rc = rtFuzzMutationDataFinalize(pThis->pMutationTop); 1542 2030 1543 2031 if (RT_SUCCESS(rc)) 1544 2032 { 1545 AssertPtr(pThis->u.Blob.pvInput); 1546 Assert(pThis->u.Blob.cbInput > 0); 1547 1548 *ppv = pThis->u.Blob.pvInput; 1549 *pcb = pThis->u.Blob.cbInput; 2033 *ppv = pThis->pMutationTop->pvInput; 2034 *pcb = pThis->pMutationTop->cbInput; 1550 2035 } 1551 2036 … … 1601 2086 1602 2087 int rc = VINF_SUCCESS; 1603 if (!pThis-> u.Blob.pvInput)1604 rc = rtFuzz InputDataFinalize(pThis);2088 if (!pThis->pMutationTop->pvInput) 2089 rc = rtFuzzMutationDataFinalize(pThis->pMutationTop); 1605 2090 1606 2091 if (RT_SUCCESS(rc)) 1607 2092 { 1608 2093 uint8_t abHash[RTMD5_HASH_SIZE]; 1609 RTMd5(pThis-> u.Blob.pvInput, pThis->u.Blob.cbInput, &abHash[0]);2094 RTMd5(pThis->pMutationTop->pvInput, pThis->pMutationTop->cbInput, &abHash[0]); 1610 2095 rc = RTMd5ToString(&abHash[0], pszDigest, cchDigest); 1611 2096 } … … 1623 2108 1624 2109 int rc = VINF_SUCCESS; 1625 if (!pThis-> u.Blob.pvInput)1626 rc = rtFuzz InputDataFinalize(pThis);2110 if (!pThis->pMutationTop->pvInput) 2111 rc = rtFuzzMutationDataFinalize(pThis->pMutationTop); 1627 2112 1628 2113 if (RT_SUCCESS(rc)) … … 1632 2117 if (RT_SUCCESS(rc)) 1633 2118 { 1634 rc = RTFileWrite(hFile, pThis-> u.Blob.pvInput, pThis->u.Blob.cbInput, NULL);2119 rc = RTFileWrite(hFile, pThis->pMutationTop->pvInput, pThis->pMutationTop->cbInput, NULL); 1635 2120 AssertRC(rc); 1636 2121 RTFileClose(hFile);
Note:
See TracChangeset
for help on using the changeset viewer.