xref: /aosp_15_r20/system/extras/simpleperf/simpleperf_writer_fuzzer.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1 /*
2  * Copyright (C) 2024 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 
18 #include <record_file.h>
19 #include "fuzzer/FuzzedDataProvider.h"
20 
21 using namespace simpleperf;
22 using namespace std;
23 using namespace android;
24 static uint32_t kMaxLen = 100;
25 static uint32_t kMinCount = 1;
26 static uint32_t kMaxCount = 1000;
27 static uint32_t kMinASCII = 0;
28 static uint32_t kMaxASCII = 255;
29 
30 class SimplePerfWriterFuzzer {
31  public:
SimplePerfWriterFuzzer(const uint8_t * data,size_t size)32   SimplePerfWriterFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
33     /**
34      * Use maximum of 80% of buffer to write in FD and save at least 20% for fuzzing other APIs
35      */
36     const int32_t dataSize = mFdp.ConsumeIntegralInRange<int32_t>(0, (size * 80) / 100);
37     std::vector<uint8_t> dataPointer = mFdp.ConsumeBytes<uint8_t>(dataSize);
38     android::base::WriteFully(mTempfile.fd, dataPointer.data(), dataPointer.size());
39   }
40   void process();
41 
42  private:
43   FuzzedDataProvider mFdp;
44   TemporaryFile mTempfile;
45   EventAttrIds mAttributeIDs;
46   bool AddEvents();
47   void CreateRecord();
48 };
49 
AddEvents()50 bool SimplePerfWriterFuzzer::AddEvents() {
51   size_t eventNo = mFdp.ConsumeIntegralInRange<size_t>(kMinCount, kMaxCount);
52   for (size_t idx = 0; idx < eventNo; ++idx) {
53     string event = mFdp.ConsumeRandomLengthString(kMaxLen);
54     if (event.size() == 0) {
55       event = "cpu-cycles";
56     }
57     uint64_t fakeID = mAttributeIDs.size();
58     mAttributeIDs.resize(mAttributeIDs.size() + 1);
59     EventAttrWithId& attrID = mAttributeIDs.back();
60     std::unique_ptr<EventTypeAndModifier> eventTypeModifier = ParseEventType(event);
61     if (!eventTypeModifier) {
62       return false;
63     }
64     attrID.attr = CreateDefaultPerfEventAttr(eventTypeModifier->event_type);
65     attrID.ids.push_back(fakeID);
66   }
67   return true;
68 }
69 
process()70 void SimplePerfWriterFuzzer::process() {
71   std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(mTempfile.path);
72   if (!writer.get()) {
73     return;
74   }
75   writer->WriteAttrSection(mAttributeIDs);
76   int32_t features = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
77 
78   if (!AddEvents()) {
79     return;
80   }
81 
82   string event = mFdp.ConsumeRandomLengthString(kMaxLen);
83   size_t index = mFdp.ConsumeIntegralInRange<size_t>(0, mAttributeIDs.size() - 1);
84   perf_event_attr attr = mAttributeIDs[index].attr;
85   MmapRecord mmprcd(
86       attr, mFdp.ConsumeBool() /* in_kernel */, getpid() /* pid */, gettid() /* tid */,
87       mFdp.ConsumeIntegral<uint64_t>() /* addr */, mFdp.ConsumeIntegral<uint64_t>() /* len */,
88       mFdp.ConsumeIntegral<uint64_t>() /* pgoff */, event,
89       mFdp.ConsumeIntegral<uint64_t>() /* event_id */, mFdp.ConsumeIntegral<uint64_t>() /* time */);
90 
91   writer->WriteRecord(mmprcd);
92   writer->BeginWriteFeatures(features);
93   std::vector<Dso*> dsos;
94   while (features-- > 0) {
95     auto invokeWriter = mFdp.PickValueInArray<const std::function<void()>>({
96         [&]() {
97           BuildId build_id(mFdp.ConsumeRandomLengthString(kMaxLen));
98           std::vector<BuildIdRecord> buildIdRecords;
99           buildIdRecords.push_back(
100               BuildIdRecord(mFdp.ConsumeBool() /* in_kernel */, getpid() /* pid */, build_id,
101                             mFdp.ConsumeRandomLengthString(kMaxLen) /* filename */));
102           writer->WriteBuildIdFeature(buildIdRecords);
103         },
104         [&]() {
105           writer->WriteFeatureString(
106               mFdp.ConsumeBool() ? PerfFileFormat::FEAT_OSRELEASE : PerfFileFormat::FEAT_ARCH,
107               mFdp.ConsumeRandomLengthString(kMaxLen) /* string */);
108         },
109         [&]() {
110           std::vector<std::string> cmdline;
111           cmdline.push_back("simpleperf");
112           int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
113           for (int32_t idx = 0; idx < iter; ++idx) {
114             cmdline.push_back(mFdp.ConsumeRandomLengthString(kMaxLen));
115           }
116           writer->WriteCmdlineFeature(cmdline);
117         },
118         [&]() {
119           int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
120           for (int32_t idx = 0; idx < iter; ++idx) {
121             DsoType dso_type =
122                 (DsoType)mFdp.ConsumeIntegralInRange<size_t>(DSO_KERNEL, DSO_UNKNOWN_FILE);
123             std::unique_ptr<Dso> dso =
124                 Dso::CreateDso(dso_type, mFdp.ConsumeRandomLengthString(kMaxLen) /* path */,
125                                mFdp.ConsumeBool() /*  force_64bit */);
126             if (dso) {
127               dsos.push_back(dso.release());
128             }
129           }
130           writer->WriteFileFeatures(dsos);
131         },
132         [&]() {
133           std::unordered_map<std::string, std::string> info_map;
134           int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
135           for (int32_t idx = 0; idx < iter; ++idx) {
136             std::string key = mFdp.ConsumeRandomLengthString(kMaxLen);
137             std::string value = mFdp.ConsumeRandomLengthString(kMaxLen);
138             info_map[key] = value;
139           }
140           writer->WriteMetaInfoFeature(info_map);
141         },
142         [&]() { writer->WriteBranchStackFeature(); },
143         [&]() {
144           std::vector<uint64_t> auxtrace;
145           int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
146           for (int32_t idx = 0; idx < iter; ++idx) {
147             auxtrace.push_back(mFdp.ConsumeIntegral<uint64_t>());
148           }
149           writer->WriteAuxTraceFeature(auxtrace);
150         },
151         [&]() {
152           DebugUnwindFeature debugVector;
153           int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
154           for (int32_t idx = 0; idx < iter; ++idx) {
155             DebugUnwindFile testFile;
156             testFile.path = mFdp.ConsumeRandomLengthString(kMaxLen);
157             testFile.size = kMaxLen;
158             debugVector.push_back(testFile);
159           }
160           writer->WriteDebugUnwindFeature(debugVector);
161         },
162     });
163     invokeWriter();
164   }
165   writer->EndWriteFeatures();
166   writer->Close();
167   for (Dso* dso : dsos) {
168     delete dso;
169     dso = nullptr;
170   }
171 }
172 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)173 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
174   SimplePerfWriterFuzzer simplePerfWriterFuzzer(data, size);
175   simplePerfWriterFuzzer.process();
176   return 0;
177 }
178