xref: /llvm-project/compiler-rt/test/fuzzer/CustomCrossOverTest.cpp (revision a1e7e401d2af002af26e1512a31e09eb2d0cf1dc)
12946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
22946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
32946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
410ab2aceSGeorge Karpenkov 
5*a1e7e401SKazuaki Ishizaki // Simple test for a custom crossover.
610ab2aceSGeorge Karpenkov #include <assert.h>
710ab2aceSGeorge Karpenkov #include <cstddef>
810ab2aceSGeorge Karpenkov #include <cstdint>
910ab2aceSGeorge Karpenkov #include <cstdlib>
1010ab2aceSGeorge Karpenkov #include <iostream>
1110ab2aceSGeorge Karpenkov #include <ostream>
1210ab2aceSGeorge Karpenkov #include <random>
1310ab2aceSGeorge Karpenkov #include <string.h>
14d0386facSKostya Serebryany #include <functional>
1510ab2aceSGeorge Karpenkov 
16d0386facSKostya Serebryany static const char *Separator = "-########-";
17d0386facSKostya Serebryany static const char *Target = "A-########-B";
1810ab2aceSGeorge Karpenkov 
19754e5840SKostya Serebryany static volatile int sink;
20754e5840SKostya Serebryany 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)2110ab2aceSGeorge Karpenkov extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
2210ab2aceSGeorge Karpenkov   assert(Data);
2310ab2aceSGeorge Karpenkov   std::string Str(reinterpret_cast<const char *>(Data), Size);
24d0386facSKostya Serebryany   static const size_t TargetHash = std::hash<std::string>{}(std::string(Target));
25d0386facSKostya Serebryany   size_t StrHash = std::hash<std::string>{}(Str);
2610ab2aceSGeorge Karpenkov 
27754e5840SKostya Serebryany   // Ensure we have 'A' and 'B' in the corpus.
28754e5840SKostya Serebryany   if (Size == 1 && *Data == 'A')
29754e5840SKostya Serebryany     sink++;
30754e5840SKostya Serebryany   if (Size == 1 && *Data == 'B')
31754e5840SKostya Serebryany     sink--;
32754e5840SKostya Serebryany 
33d0386facSKostya Serebryany   if (TargetHash == StrHash) {
3410ab2aceSGeorge Karpenkov     std::cout << "BINGO; Found the target, exiting\n" << std::flush;
3510ab2aceSGeorge Karpenkov     exit(1);
3610ab2aceSGeorge Karpenkov   }
3710ab2aceSGeorge Karpenkov   return 0;
3810ab2aceSGeorge Karpenkov }
3910ab2aceSGeorge Karpenkov 
LLVMFuzzerCustomCrossOver(const uint8_t * Data1,size_t Size1,const uint8_t * Data2,size_t Size2,uint8_t * Out,size_t MaxOutSize,unsigned int Seed)4010ab2aceSGeorge Karpenkov extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
4110ab2aceSGeorge Karpenkov                                             const uint8_t *Data2, size_t Size2,
4210ab2aceSGeorge Karpenkov                                             uint8_t *Out, size_t MaxOutSize,
4310ab2aceSGeorge Karpenkov                                             unsigned int Seed) {
44d0386facSKostya Serebryany   static size_t Printed;
4510ab2aceSGeorge Karpenkov   static size_t SeparatorLen = strlen(Separator);
4610ab2aceSGeorge Karpenkov 
47d0386facSKostya Serebryany   if (Printed++ < 32)
48d0386facSKostya Serebryany     std::cerr << "In LLVMFuzzerCustomCrossover " << Size1 << " " << Size2 << "\n";
4910ab2aceSGeorge Karpenkov 
50d0386facSKostya Serebryany   size_t Size = Size1 + Size2 + SeparatorLen;
5110ab2aceSGeorge Karpenkov 
5210ab2aceSGeorge Karpenkov   if (Size > MaxOutSize)
5310ab2aceSGeorge Karpenkov     return 0;
5410ab2aceSGeorge Karpenkov 
55d0386facSKostya Serebryany   memcpy(Out, Data1, Size1);
56d0386facSKostya Serebryany   memcpy(Out + Size1, Separator, SeparatorLen);
57d0386facSKostya Serebryany   memcpy(Out + Size1 + SeparatorLen, Data2, Size2);
5810ab2aceSGeorge Karpenkov 
59d0386facSKostya Serebryany   return Size;
6010ab2aceSGeorge Karpenkov }
61