1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <functional>
18 #include <iostream>
19 #include <vector>
20 
21 #include <unwindstack/JitDebug.h>
22 #include <unwindstack/Maps.h>
23 #include <unwindstack/Memory.h>
24 #include <unwindstack/Unwinder.h>
25 
26 #include "../MemoryFake.h"
27 #include "UnwinderComponentCreator.h"
28 #include "fuzzer/FuzzedDataProvider.h"
29 
30 namespace unwindstack {
31 
32 static constexpr int kMaxUnwindStringLen = 50;
33 static constexpr int kMaxUnwindStrings = 50;
34 
PerformUnwind(FuzzedDataProvider * data_provider,Unwinder * unwinder)35 void PerformUnwind(FuzzedDataProvider* data_provider, Unwinder* unwinder) {
36   // 0 = don't set any values
37   // 1 = set initial_map_names_to_skip
38   // 2 = set map_suffixes_to_ignore
39   // 3 = set both
40   uint8_t set_values = data_provider->ConsumeIntegral<uint8_t>() % 4;
41   if (set_values == 0) {
42     unwinder->Unwind();
43   } else if (set_values == 1) {
44     // Only setting initial_map_names_to_skip
45     std::vector<std::string> skip_names =
46         GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
47 
48     unwinder->Unwind(&skip_names, nullptr);
49   } else if (set_values == 2) {
50     // Only setting map_suffixes_to_ignore
51     std::vector<std::string> ignore_suffixes =
52         GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
53 
54     unwinder->Unwind(nullptr, &ignore_suffixes);
55   } else if (set_values == 3) {
56     // Setting both values
57     std::vector<std::string> skip_names =
58         GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
59     std::vector<std::string> ignore_suffixes =
60         GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
61 
62     unwinder->Unwind(&skip_names, &ignore_suffixes);
63   }
64 }
65 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)66 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
67   FuzzedDataProvider data_provider(data, size);
68 
69   // We need to construct an unwinder.
70   // Generate the Maps:
71   std::unique_ptr<Maps> maps = GetMaps(&data_provider);
72 
73   // Generate the Regs:
74   uint8_t arch_val = data_provider.ConsumeIntegralInRange<uint8_t>(1, kArchCount);
75   ArchEnum arch = static_cast<ArchEnum>(arch_val);
76   std::unique_ptr<Regs> regs = GetRegisters(arch);
77 
78   // Generate memory:
79   std::shared_ptr<Memory> memory = std::make_shared<MemoryFake>();
80   PutElfFilesInMemory(reinterpret_cast<MemoryFake*>(memory.get()), &data_provider);
81 
82   size_t max_frames = data_provider.ConsumeIntegralInRange<size_t>(0, 5000);
83 
84   std::unique_ptr<JitDebug> jit_debug_ptr = std::make_unique<JitDebug>(memory);
85 
86   // Create instance
87   Unwinder unwinder(max_frames, maps.get(), regs.get(), memory);
88   unwinder.SetJitDebug(jit_debug_ptr.get(), arch);
89   unwinder.SetResolveNames(data_provider.ConsumeBool());
90   // Call unwind
91   PerformUnwind(&data_provider, &unwinder);
92 
93   // Run some additional logic that changes after unwind
94   uint64_t pc = data_provider.ConsumeIntegral<uint64_t>();
95   unwinder.BuildFrameFromPcOnly(pc);
96   unwinder.ConsumeFrames();
97   return 0;
98 }
99 }  // namespace unwindstack
100