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 <atomic>
18 #include <thread>
19
20 #include "fuzzer/FuzzedDataProvider.h"
21 #include "utils/ProcessCallStack.h"
22 using android::ProcessCallStack;
23
24 static constexpr int MAX_NAME_SIZE = 1000;
25 static constexpr int MAX_LOG_META_SIZE = 1000;
26 static constexpr uint8_t MAX_THREADS = 10;
27
28 std::atomic_bool ranCallStackUpdate(false);
loop()29 void loop() {
30 while (!ranCallStackUpdate.load()) {
31 std::this_thread::sleep_for(std::chrono::milliseconds(50));
32 }
33 }
34
spawnThreads(FuzzedDataProvider * dataProvider)35 void spawnThreads(FuzzedDataProvider* dataProvider) {
36 std::vector<std::thread> threads = std::vector<std::thread>();
37
38 // Get the number of threads to generate
39 uint8_t count = dataProvider->ConsumeIntegralInRange<uint8_t>(1, MAX_THREADS);
40
41 // Generate threads
42 for (uint8_t i = 0; i < count; i++) {
43 std::string threadName =
44 dataProvider->ConsumeRandomLengthString(MAX_NAME_SIZE).append(std::to_string(i));
45 std::thread th = std::thread(loop);
46 pthread_setname_np(th.native_handle(), threadName.c_str());
47 threads.push_back(std::move(th));
48 }
49
50 // Collect thread information
51 ProcessCallStack callStack = ProcessCallStack();
52 callStack.update();
53
54 // Tell our patiently waiting threads they can be done now.
55 ranCallStackUpdate.store(true);
56
57 std::string logTag = dataProvider->ConsumeRandomLengthString(MAX_LOG_META_SIZE);
58 std::string prefix = dataProvider->ConsumeRandomLengthString(MAX_LOG_META_SIZE);
59 // Both of these, along with dump, all call print() under the hood,
60 // Which is covered by the Printer fuzzer.
61 callStack.log(logTag.c_str());
62 callStack.toString(prefix.c_str());
63
64 // Check size
65 callStack.size();
66
67 // wait for any remaining threads
68 for (auto& thread : threads) {
69 thread.join();
70 }
71 }
72
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)73 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
74 FuzzedDataProvider dataProvider(data, size);
75 spawnThreads(&dataProvider);
76 return 0;
77 }
78