1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at:
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker *
16*288bf522SAndroid Build Coastguard Worker */
17*288bf522SAndroid Build Coastguard Worker
18*288bf522SAndroid Build Coastguard Worker #include <record_file.h>
19*288bf522SAndroid Build Coastguard Worker #include "fuzzer/FuzzedDataProvider.h"
20*288bf522SAndroid Build Coastguard Worker
21*288bf522SAndroid Build Coastguard Worker using namespace simpleperf;
22*288bf522SAndroid Build Coastguard Worker using namespace std;
23*288bf522SAndroid Build Coastguard Worker using namespace android;
24*288bf522SAndroid Build Coastguard Worker static uint32_t kMaxLen = 100;
25*288bf522SAndroid Build Coastguard Worker static uint32_t kMinCount = 1;
26*288bf522SAndroid Build Coastguard Worker static uint32_t kMaxCount = 1000;
27*288bf522SAndroid Build Coastguard Worker static uint32_t kMinASCII = 0;
28*288bf522SAndroid Build Coastguard Worker static uint32_t kMaxASCII = 255;
29*288bf522SAndroid Build Coastguard Worker
30*288bf522SAndroid Build Coastguard Worker class SimplePerfWriterFuzzer {
31*288bf522SAndroid Build Coastguard Worker public:
SimplePerfWriterFuzzer(const uint8_t * data,size_t size)32*288bf522SAndroid Build Coastguard Worker SimplePerfWriterFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
33*288bf522SAndroid Build Coastguard Worker /**
34*288bf522SAndroid Build Coastguard Worker * Use maximum of 80% of buffer to write in FD and save at least 20% for fuzzing other APIs
35*288bf522SAndroid Build Coastguard Worker */
36*288bf522SAndroid Build Coastguard Worker const int32_t dataSize = mFdp.ConsumeIntegralInRange<int32_t>(0, (size * 80) / 100);
37*288bf522SAndroid Build Coastguard Worker std::vector<uint8_t> dataPointer = mFdp.ConsumeBytes<uint8_t>(dataSize);
38*288bf522SAndroid Build Coastguard Worker android::base::WriteFully(mTempfile.fd, dataPointer.data(), dataPointer.size());
39*288bf522SAndroid Build Coastguard Worker }
40*288bf522SAndroid Build Coastguard Worker void process();
41*288bf522SAndroid Build Coastguard Worker
42*288bf522SAndroid Build Coastguard Worker private:
43*288bf522SAndroid Build Coastguard Worker FuzzedDataProvider mFdp;
44*288bf522SAndroid Build Coastguard Worker TemporaryFile mTempfile;
45*288bf522SAndroid Build Coastguard Worker EventAttrIds mAttributeIDs;
46*288bf522SAndroid Build Coastguard Worker bool AddEvents();
47*288bf522SAndroid Build Coastguard Worker void CreateRecord();
48*288bf522SAndroid Build Coastguard Worker };
49*288bf522SAndroid Build Coastguard Worker
AddEvents()50*288bf522SAndroid Build Coastguard Worker bool SimplePerfWriterFuzzer::AddEvents() {
51*288bf522SAndroid Build Coastguard Worker size_t eventNo = mFdp.ConsumeIntegralInRange<size_t>(kMinCount, kMaxCount);
52*288bf522SAndroid Build Coastguard Worker for (size_t idx = 0; idx < eventNo; ++idx) {
53*288bf522SAndroid Build Coastguard Worker string event = mFdp.ConsumeRandomLengthString(kMaxLen);
54*288bf522SAndroid Build Coastguard Worker if (event.size() == 0) {
55*288bf522SAndroid Build Coastguard Worker event = "cpu-cycles";
56*288bf522SAndroid Build Coastguard Worker }
57*288bf522SAndroid Build Coastguard Worker uint64_t fakeID = mAttributeIDs.size();
58*288bf522SAndroid Build Coastguard Worker mAttributeIDs.resize(mAttributeIDs.size() + 1);
59*288bf522SAndroid Build Coastguard Worker EventAttrWithId& attrID = mAttributeIDs.back();
60*288bf522SAndroid Build Coastguard Worker std::unique_ptr<EventTypeAndModifier> eventTypeModifier = ParseEventType(event);
61*288bf522SAndroid Build Coastguard Worker if (!eventTypeModifier) {
62*288bf522SAndroid Build Coastguard Worker return false;
63*288bf522SAndroid Build Coastguard Worker }
64*288bf522SAndroid Build Coastguard Worker attrID.attr = CreateDefaultPerfEventAttr(eventTypeModifier->event_type);
65*288bf522SAndroid Build Coastguard Worker attrID.ids.push_back(fakeID);
66*288bf522SAndroid Build Coastguard Worker }
67*288bf522SAndroid Build Coastguard Worker return true;
68*288bf522SAndroid Build Coastguard Worker }
69*288bf522SAndroid Build Coastguard Worker
process()70*288bf522SAndroid Build Coastguard Worker void SimplePerfWriterFuzzer::process() {
71*288bf522SAndroid Build Coastguard Worker std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(mTempfile.path);
72*288bf522SAndroid Build Coastguard Worker if (!writer.get()) {
73*288bf522SAndroid Build Coastguard Worker return;
74*288bf522SAndroid Build Coastguard Worker }
75*288bf522SAndroid Build Coastguard Worker writer->WriteAttrSection(mAttributeIDs);
76*288bf522SAndroid Build Coastguard Worker int32_t features = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
77*288bf522SAndroid Build Coastguard Worker
78*288bf522SAndroid Build Coastguard Worker if (!AddEvents()) {
79*288bf522SAndroid Build Coastguard Worker return;
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker
82*288bf522SAndroid Build Coastguard Worker string event = mFdp.ConsumeRandomLengthString(kMaxLen);
83*288bf522SAndroid Build Coastguard Worker size_t index = mFdp.ConsumeIntegralInRange<size_t>(0, mAttributeIDs.size() - 1);
84*288bf522SAndroid Build Coastguard Worker perf_event_attr attr = mAttributeIDs[index].attr;
85*288bf522SAndroid Build Coastguard Worker MmapRecord mmprcd(
86*288bf522SAndroid Build Coastguard Worker attr, mFdp.ConsumeBool() /* in_kernel */, getpid() /* pid */, gettid() /* tid */,
87*288bf522SAndroid Build Coastguard Worker mFdp.ConsumeIntegral<uint64_t>() /* addr */, mFdp.ConsumeIntegral<uint64_t>() /* len */,
88*288bf522SAndroid Build Coastguard Worker mFdp.ConsumeIntegral<uint64_t>() /* pgoff */, event,
89*288bf522SAndroid Build Coastguard Worker mFdp.ConsumeIntegral<uint64_t>() /* event_id */, mFdp.ConsumeIntegral<uint64_t>() /* time */);
90*288bf522SAndroid Build Coastguard Worker
91*288bf522SAndroid Build Coastguard Worker writer->WriteRecord(mmprcd);
92*288bf522SAndroid Build Coastguard Worker writer->BeginWriteFeatures(features);
93*288bf522SAndroid Build Coastguard Worker std::vector<Dso*> dsos;
94*288bf522SAndroid Build Coastguard Worker while (features-- > 0) {
95*288bf522SAndroid Build Coastguard Worker auto invokeWriter = mFdp.PickValueInArray<const std::function<void()>>({
96*288bf522SAndroid Build Coastguard Worker [&]() {
97*288bf522SAndroid Build Coastguard Worker BuildId build_id(mFdp.ConsumeRandomLengthString(kMaxLen));
98*288bf522SAndroid Build Coastguard Worker std::vector<BuildIdRecord> buildIdRecords;
99*288bf522SAndroid Build Coastguard Worker buildIdRecords.push_back(
100*288bf522SAndroid Build Coastguard Worker BuildIdRecord(mFdp.ConsumeBool() /* in_kernel */, getpid() /* pid */, build_id,
101*288bf522SAndroid Build Coastguard Worker mFdp.ConsumeRandomLengthString(kMaxLen) /* filename */));
102*288bf522SAndroid Build Coastguard Worker writer->WriteBuildIdFeature(buildIdRecords);
103*288bf522SAndroid Build Coastguard Worker },
104*288bf522SAndroid Build Coastguard Worker [&]() {
105*288bf522SAndroid Build Coastguard Worker writer->WriteFeatureString(
106*288bf522SAndroid Build Coastguard Worker mFdp.ConsumeBool() ? PerfFileFormat::FEAT_OSRELEASE : PerfFileFormat::FEAT_ARCH,
107*288bf522SAndroid Build Coastguard Worker mFdp.ConsumeRandomLengthString(kMaxLen) /* string */);
108*288bf522SAndroid Build Coastguard Worker },
109*288bf522SAndroid Build Coastguard Worker [&]() {
110*288bf522SAndroid Build Coastguard Worker std::vector<std::string> cmdline;
111*288bf522SAndroid Build Coastguard Worker cmdline.push_back("simpleperf");
112*288bf522SAndroid Build Coastguard Worker int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
113*288bf522SAndroid Build Coastguard Worker for (int32_t idx = 0; idx < iter; ++idx) {
114*288bf522SAndroid Build Coastguard Worker cmdline.push_back(mFdp.ConsumeRandomLengthString(kMaxLen));
115*288bf522SAndroid Build Coastguard Worker }
116*288bf522SAndroid Build Coastguard Worker writer->WriteCmdlineFeature(cmdline);
117*288bf522SAndroid Build Coastguard Worker },
118*288bf522SAndroid Build Coastguard Worker [&]() {
119*288bf522SAndroid Build Coastguard Worker int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
120*288bf522SAndroid Build Coastguard Worker for (int32_t idx = 0; idx < iter; ++idx) {
121*288bf522SAndroid Build Coastguard Worker DsoType dso_type =
122*288bf522SAndroid Build Coastguard Worker (DsoType)mFdp.ConsumeIntegralInRange<size_t>(DSO_KERNEL, DSO_UNKNOWN_FILE);
123*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Dso> dso =
124*288bf522SAndroid Build Coastguard Worker Dso::CreateDso(dso_type, mFdp.ConsumeRandomLengthString(kMaxLen) /* path */,
125*288bf522SAndroid Build Coastguard Worker mFdp.ConsumeBool() /* force_64bit */);
126*288bf522SAndroid Build Coastguard Worker if (dso) {
127*288bf522SAndroid Build Coastguard Worker dsos.push_back(dso.release());
128*288bf522SAndroid Build Coastguard Worker }
129*288bf522SAndroid Build Coastguard Worker }
130*288bf522SAndroid Build Coastguard Worker writer->WriteFileFeatures(dsos);
131*288bf522SAndroid Build Coastguard Worker },
132*288bf522SAndroid Build Coastguard Worker [&]() {
133*288bf522SAndroid Build Coastguard Worker std::unordered_map<std::string, std::string> info_map;
134*288bf522SAndroid Build Coastguard Worker int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
135*288bf522SAndroid Build Coastguard Worker for (int32_t idx = 0; idx < iter; ++idx) {
136*288bf522SAndroid Build Coastguard Worker std::string key = mFdp.ConsumeRandomLengthString(kMaxLen);
137*288bf522SAndroid Build Coastguard Worker std::string value = mFdp.ConsumeRandomLengthString(kMaxLen);
138*288bf522SAndroid Build Coastguard Worker info_map[key] = value;
139*288bf522SAndroid Build Coastguard Worker }
140*288bf522SAndroid Build Coastguard Worker writer->WriteMetaInfoFeature(info_map);
141*288bf522SAndroid Build Coastguard Worker },
142*288bf522SAndroid Build Coastguard Worker [&]() { writer->WriteBranchStackFeature(); },
143*288bf522SAndroid Build Coastguard Worker [&]() {
144*288bf522SAndroid Build Coastguard Worker std::vector<uint64_t> auxtrace;
145*288bf522SAndroid Build Coastguard Worker int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
146*288bf522SAndroid Build Coastguard Worker for (int32_t idx = 0; idx < iter; ++idx) {
147*288bf522SAndroid Build Coastguard Worker auxtrace.push_back(mFdp.ConsumeIntegral<uint64_t>());
148*288bf522SAndroid Build Coastguard Worker }
149*288bf522SAndroid Build Coastguard Worker writer->WriteAuxTraceFeature(auxtrace);
150*288bf522SAndroid Build Coastguard Worker },
151*288bf522SAndroid Build Coastguard Worker [&]() {
152*288bf522SAndroid Build Coastguard Worker DebugUnwindFeature debugVector;
153*288bf522SAndroid Build Coastguard Worker int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
154*288bf522SAndroid Build Coastguard Worker for (int32_t idx = 0; idx < iter; ++idx) {
155*288bf522SAndroid Build Coastguard Worker DebugUnwindFile testFile;
156*288bf522SAndroid Build Coastguard Worker testFile.path = mFdp.ConsumeRandomLengthString(kMaxLen);
157*288bf522SAndroid Build Coastguard Worker testFile.size = kMaxLen;
158*288bf522SAndroid Build Coastguard Worker debugVector.push_back(testFile);
159*288bf522SAndroid Build Coastguard Worker }
160*288bf522SAndroid Build Coastguard Worker writer->WriteDebugUnwindFeature(debugVector);
161*288bf522SAndroid Build Coastguard Worker },
162*288bf522SAndroid Build Coastguard Worker });
163*288bf522SAndroid Build Coastguard Worker invokeWriter();
164*288bf522SAndroid Build Coastguard Worker }
165*288bf522SAndroid Build Coastguard Worker writer->EndWriteFeatures();
166*288bf522SAndroid Build Coastguard Worker writer->Close();
167*288bf522SAndroid Build Coastguard Worker for (Dso* dso : dsos) {
168*288bf522SAndroid Build Coastguard Worker delete dso;
169*288bf522SAndroid Build Coastguard Worker dso = nullptr;
170*288bf522SAndroid Build Coastguard Worker }
171*288bf522SAndroid Build Coastguard Worker }
172*288bf522SAndroid Build Coastguard Worker
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)173*288bf522SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
174*288bf522SAndroid Build Coastguard Worker SimplePerfWriterFuzzer simplePerfWriterFuzzer(data, size);
175*288bf522SAndroid Build Coastguard Worker simplePerfWriterFuzzer.process();
176*288bf522SAndroid Build Coastguard Worker return 0;
177*288bf522SAndroid Build Coastguard Worker }
178