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