1 //===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // Cross over test inputs. 9 //===----------------------------------------------------------------------===// 10 11 #include "FuzzerDefs.h" 12 #include "FuzzerMutate.h" 13 #include "FuzzerRandom.h" 14 #include <cstring> 15 16 namespace fuzzer { 17 18 // Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out. 19 size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1, 20 const uint8_t *Data2, size_t Size2, 21 uint8_t *Out, size_t MaxOutSize) { 22 assert(Size1 || Size2); 23 MaxOutSize = Rand(MaxOutSize) + 1; 24 size_t OutPos = 0; 25 size_t Pos1 = 0; 26 size_t Pos2 = 0; 27 size_t *InPos = &Pos1; 28 size_t InSize = Size1; 29 const uint8_t *Data = Data1; 30 bool CurrentlyUsingFirstData = true; 31 while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) { 32 // Merge a part of Data into Out. 33 size_t OutSizeLeft = MaxOutSize - OutPos; 34 if (*InPos < InSize) { 35 size_t InSizeLeft = InSize - *InPos; 36 size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft); 37 size_t ExtraSize = Rand(MaxExtraSize) + 1; 38 memcpy(Out + OutPos, Data + *InPos, ExtraSize); 39 OutPos += ExtraSize; 40 (*InPos) += ExtraSize; 41 } 42 // Use the other input data on the next iteration. 43 InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1; 44 InSize = CurrentlyUsingFirstData ? Size2 : Size1; 45 Data = CurrentlyUsingFirstData ? Data2 : Data1; 46 CurrentlyUsingFirstData = !CurrentlyUsingFirstData; 47 } 48 return OutPos; 49 } 50 51 } // namespace fuzzer 52