blob: 37689f7434a27b45fd4c10dad4f448c23764478b [file] [log] [blame]
Florian Mayer60d1e132018-01-26 15:00:52 +00001/*
2 * Copyright (C) 2018 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 <stddef.h>
18#include <stdint.h>
19#include <unistd.h>
20
21#include "perfetto/base/logging.h"
22#include "perfetto/base/task_runner.h"
23#include "perfetto/base/utils.h"
24#include "perfetto/ipc/host.h"
Hector Dearmanfaa22f82018-02-14 12:02:51 +000025#include "perfetto/trace/test_event.pbzero.h"
Florian Mayer60d1e132018-01-26 15:00:52 +000026#include "perfetto/trace/trace_packet.pb.h"
27#include "perfetto/trace/trace_packet.pbzero.h"
28#include "perfetto/tracing/core/data_source_config.h"
29#include "perfetto/tracing/core/data_source_descriptor.h"
30#include "perfetto/tracing/core/producer.h"
31#include "perfetto/tracing/core/trace_writer.h"
32#include "perfetto/tracing/ipc/producer_ipc_client.h"
33#include "perfetto/tracing/ipc/service_ipc_host.h"
34#include "src/base/test/test_task_runner.h"
35#include "test/fake_consumer.h"
36#include "test/task_runner_thread.h"
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000037#include "test/task_runner_thread_delegates.h"
Florian Mayer60d1e132018-01-26 15:00:52 +000038
Florian Mayer60d1e132018-01-26 15:00:52 +000039namespace perfetto {
40namespace shm_fuzz {
41
Florian Mayer43374ba2018-02-16 13:35:16 +000042static const char* kProducerSocket = tempnam("/tmp", "perfetto-producer");
43static const char* kConsumerSocket = tempnam("/tmp", "perfetto-consumer");
44
Florian Mayer60d1e132018-01-26 15:00:52 +000045// Fake producer writing a protozero message of data into shared memory
46// buffer, followed by a sentinel message to signal completion to the
47// consumer.
48class FakeProducer : public Producer {
49 public:
Florian Mayer20c2c722018-02-15 14:10:16 +000050 FakeProducer(std::string name,
51 const uint8_t* data,
52 size_t size,
Lalit Magantidd95ef92018-03-23 09:42:48 +000053 std::function<void()> on_produced_and_committed)
54 : name_(std::move(name)),
55 data_(data),
56 size_(size),
57 on_produced_and_committed_(on_produced_and_committed) {}
Florian Mayer60d1e132018-01-26 15:00:52 +000058
59 void Connect(const char* socket_name, base::TaskRunner* task_runner) {
60 endpoint_ = ProducerIPCClient::Connect(socket_name, this, task_runner);
61 }
62
63 void OnConnect() override {
64 DataSourceDescriptor descriptor;
65 descriptor.set_name(name_);
66 endpoint_->RegisterDataSource(descriptor,
67 [this](DataSourceID id) { id_ = id; });
68 }
69
70 void OnDisconnect() override {}
71
72 void CreateDataSourceInstance(
73 DataSourceInstanceID,
74 const DataSourceConfig& source_config) override {
Lalit Magantidd95ef92018-03-23 09:42:48 +000075 auto trace_writer = endpoint_->CreateTraceWriter(
76 static_cast<BufferID>(source_config.target_buffer()));
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000077 {
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000078 auto packet = trace_writer->NewTracePacket();
79 packet->stream_writer_->WriteBytes(data_, size_);
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000080 }
Lalit Magantidd95ef92018-03-23 09:42:48 +000081 trace_writer->Flush();
82
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000083 {
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000084 auto end_packet = trace_writer->NewTracePacket();
85 end_packet->set_for_testing()->set_str("end");
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000086 }
Lalit Magantidd95ef92018-03-23 09:42:48 +000087 trace_writer->Flush(on_produced_and_committed_);
Florian Mayer60d1e132018-01-26 15:00:52 +000088 }
89
90 void TearDownDataSourceInstance(DataSourceInstanceID) override {}
Isabelle Taylor69faa902018-03-21 15:42:03 +000091 void OnTracingStart() override {}
92 void OnTracingStop() override {}
Florian Mayer60d1e132018-01-26 15:00:52 +000093
94 private:
95 const std::string name_;
96 const uint8_t* data_;
97 const size_t size_;
98 DataSourceID id_ = 0;
99 std::unique_ptr<Service::ProducerEndpoint> endpoint_;
Lalit Magantidd95ef92018-03-23 09:42:48 +0000100 std::function<void()> on_produced_and_committed_;
Florian Mayer60d1e132018-01-26 15:00:52 +0000101};
102
103class FakeProducerDelegate : public ThreadDelegate {
104 public:
Lalit Magantidd95ef92018-03-23 09:42:48 +0000105 FakeProducerDelegate(const uint8_t* data,
106 size_t size,
107 std::function<void()> on_produced_and_committed)
108 : data_(data),
109 size_(size),
110 on_produced_and_committed_(on_produced_and_committed) {}
Florian Mayer60d1e132018-01-26 15:00:52 +0000111 ~FakeProducerDelegate() override = default;
112
113 void Initialize(base::TaskRunner* task_runner) override {
Florian Mayer20c2c722018-02-15 14:10:16 +0000114 producer_.reset(new FakeProducer("android.perfetto.FakeProducer", data_,
Lalit Magantidd95ef92018-03-23 09:42:48 +0000115 size_, on_produced_and_committed_));
Florian Mayer43374ba2018-02-16 13:35:16 +0000116 producer_->Connect(kProducerSocket, task_runner);
Florian Mayer60d1e132018-01-26 15:00:52 +0000117 }
118
119 private:
120 std::unique_ptr<FakeProducer> producer_;
121 const uint8_t* data_;
122 const size_t size_;
Lalit Magantidd95ef92018-03-23 09:42:48 +0000123 std::function<void()> on_produced_and_committed_;
Florian Mayer60d1e132018-01-26 15:00:52 +0000124};
125
Florian Mayer60d1e132018-01-26 15:00:52 +0000126int FuzzSharedMemory(const uint8_t* data, size_t size);
127
128int FuzzSharedMemory(const uint8_t* data, size_t size) {
Lalit Magantidd95ef92018-03-23 09:42:48 +0000129 base::TestTaskRunner task_runner;
130
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000131 TaskRunnerThread service_thread("perfetto.svc");
132 service_thread.Start(std::unique_ptr<ServiceDelegate>(
133 new ServiceDelegate(kProducerSocket, kConsumerSocket)));
Florian Mayer60d1e132018-01-26 15:00:52 +0000134
Lalit Magantidd95ef92018-03-23 09:42:48 +0000135 auto on_produced_and_committed =
136 task_runner.CreateCheckpoint("produced.and.committed");
137 auto posted_on_produced_and_committed = [&task_runner,
138 &on_produced_and_committed] {
139 task_runner.PostTask(on_produced_and_committed);
140 };
141 TaskRunnerThread producer_thread("perfetto.prd");
142 producer_thread.Start(std::unique_ptr<FakeProducerDelegate>(
143 new FakeProducerDelegate(data, size, posted_on_produced_and_committed)));
144
Florian Mayer60d1e132018-01-26 15:00:52 +0000145 // Setup the TraceConfig for the consumer.
146 TraceConfig trace_config;
Florian Mayer4c3580f2018-02-12 15:59:55 +0000147 trace_config.add_buffers()->set_size_kb(8);
Florian Mayer60d1e132018-01-26 15:00:52 +0000148
Lalit Magantidd95ef92018-03-23 09:42:48 +0000149 // Create the buffer for the fake producer.
Florian Mayer60d1e132018-01-26 15:00:52 +0000150 auto* ds_config = trace_config.add_data_sources()->mutable_config();
151 ds_config->set_name("android.perfetto.FakeProducer");
152 ds_config->set_target_buffer(0);
153
Lalit Magantidd95ef92018-03-23 09:42:48 +0000154 auto on_readback_complete = task_runner.CreateCheckpoint("readback.complete");
155 auto on_consumer_data = [&on_readback_complete](
156 std::vector<TracePacket> packets, bool has_more) {
Florian Mayer60d1e132018-01-26 15:00:52 +0000157 for (auto& p : packets) {
158 p.Decode();
Hector Dearmanfaa22f82018-02-14 12:02:51 +0000159 if (p->for_testing().str() == "end")
Lalit Magantidd95ef92018-03-23 09:42:48 +0000160 on_readback_complete();
Florian Mayer60d1e132018-01-26 15:00:52 +0000161 }
162 };
Lalit Magantidd95ef92018-03-23 09:42:48 +0000163
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000164 auto on_connect = task_runner.CreateCheckpoint("consumer.connected");
165 FakeConsumer consumer(trace_config, std::move(on_connect),
Lalit Magantidd95ef92018-03-23 09:42:48 +0000166 std::move(on_consumer_data), &task_runner);
167
Florian Mayer43374ba2018-02-16 13:35:16 +0000168 consumer.Connect(kConsumerSocket);
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000169 task_runner.RunUntilCheckpoint("consumer.connected");
Florian Mayer20c2c722018-02-15 14:10:16 +0000170
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000171 consumer.EnableTracing();
Lalit Magantidd95ef92018-03-23 09:42:48 +0000172 task_runner.RunUntilCheckpoint("produced.and.committed");
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000173
Lalit Magantidd95ef92018-03-23 09:42:48 +0000174 consumer.ReadTraceData();
175 task_runner.RunUntilCheckpoint("readback.complete");
176
177 consumer.Disconnect();
178
Florian Mayer60d1e132018-01-26 15:00:52 +0000179 return 0;
180}
181
182} // namespace shm_fuzz
183} // namespace perfetto
184
185extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
186
187extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
188 return perfetto::shm_fuzz::FuzzSharedMemory(data, size);
189}