1326943Sdim//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// 2326943Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6326943Sdim// 7326943Sdim//===----------------------------------------------------------------------===// 8326943Sdim// Cross over test inputs. 9326943Sdim//===----------------------------------------------------------------------===// 10326943Sdim 11326943Sdim#include "FuzzerDefs.h" 12326943Sdim#include "FuzzerMutate.h" 13326943Sdim#include "FuzzerRandom.h" 14326943Sdim#include <cstring> 15326943Sdim 16326943Sdimnamespace fuzzer { 17326943Sdim 18326943Sdim// Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out. 19326943Sdimsize_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1, 20326943Sdim const uint8_t *Data2, size_t Size2, 21326943Sdim uint8_t *Out, size_t MaxOutSize) { 22326943Sdim assert(Size1 || Size2); 23326943Sdim MaxOutSize = Rand(MaxOutSize) + 1; 24326943Sdim size_t OutPos = 0; 25326943Sdim size_t Pos1 = 0; 26326943Sdim size_t Pos2 = 0; 27326943Sdim size_t *InPos = &Pos1; 28326943Sdim size_t InSize = Size1; 29326943Sdim const uint8_t *Data = Data1; 30326943Sdim bool CurrentlyUsingFirstData = true; 31326943Sdim while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) { 32326943Sdim // Merge a part of Data into Out. 33326943Sdim size_t OutSizeLeft = MaxOutSize - OutPos; 34326943Sdim if (*InPos < InSize) { 35326943Sdim size_t InSizeLeft = InSize - *InPos; 36326943Sdim size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft); 37326943Sdim size_t ExtraSize = Rand(MaxExtraSize) + 1; 38326943Sdim memcpy(Out + OutPos, Data + *InPos, ExtraSize); 39326943Sdim OutPos += ExtraSize; 40326943Sdim (*InPos) += ExtraSize; 41326943Sdim } 42326943Sdim // Use the other input data on the next iteration. 43326943Sdim InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1; 44326943Sdim InSize = CurrentlyUsingFirstData ? Size2 : Size1; 45326943Sdim Data = CurrentlyUsingFirstData ? Data2 : Data1; 46326943Sdim CurrentlyUsingFirstData = !CurrentlyUsingFirstData; 47326943Sdim } 48326943Sdim return OutPos; 49326943Sdim} 50326943Sdim 51326943Sdim} // namespace fuzzer 52