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