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 <android-base/logging.h>
18 #include <fuzzer/FuzzedDataProvider.h>
19 #include <gmock/gmock.h>
20 #include "ClientConfig.pb.h"
21 #include "Common.h"
22 #include "GrpcGraph.h"
23 #include "GrpcGraphServerImpl.h"
24 
25 using ::android::automotive::computepipe::runner::ClientConfig;
26 
27 namespace android {
28 namespace automotive {
29 namespace computepipe {
30 namespace graph {
31 
32 namespace {
33 
34 enum GRPC_GRAPH_FUZZ_FUNCS {
35     GRAPH_RUNNER_BASE_ENUM,
36     DISPATCH_PIXEL_DATA,            /* verify dispatchPixelData */
37     DISPATCH_SERIALIZED_DATA,       /* dispatchSerializedData */
38     DISPATCH_GRAPH_TERMINATION_MSG, /* dispatchGraphTerminationMessage */
39     RUNNER_COMP_BASE_ENUM
40 };
41 
DoInitialization()42 bool DoInitialization() {
43     // Initialization goes here
44     std::shared_ptr<GrpcGraphServerImpl> server;
45     server = std::make_shared<GrpcGraphServerImpl>(runner::test::kAddress);
46     std::thread t = std::thread([server]() { server->startServer(); });
47     t.detach();
48     std::this_thread::sleep_for(std::chrono::seconds(1));
49     return true;
50 }
51 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)52 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
53     static bool initialized = DoInitialization();
54     std::shared_ptr<PrebuiltEngineInterfaceImpl> engine;
55     std::unique_ptr<GrpcGraph> graph = std::make_unique<GrpcGraph>();
56     engine = std::make_shared<PrebuiltEngineInterfaceImpl>();
57     Status status = graph->initialize(runner::test::kAddress, engine);
58     if (status != Status::SUCCESS) {
59         LOG(ERROR) << "Initialization of GrpcGraph failed, aborting...";
60         exit(1);
61     }
62 
63     // Fuzz goes here
64     FuzzedDataProvider fdp(data, size);
65     while (fdp.remaining_bytes() > runner::test::kMaxFuzzerConsumedBytes) {
66         switch (fdp.ConsumeIntegralInRange<uint32_t>(0, API_SUM - 1)) {
67             case GET_GRAPH_TYPE: {
68                 graph->GetGraphType();
69                 break;
70             }
71             case GET_GRAPH_STATE: {
72                 graph->GetGraphState();
73                 break;
74             }
75             case GET_STATUS: {
76                 graph->GetStatus();
77                 break;
78             }
79             case GET_ERROR_MESSAGE: {
80                 graph->GetErrorMessage();
81                 break;
82             }
83             case GET_SUPPORTED_GRAPH_CONFIGS: {
84                 graph->GetSupportedGraphConfigs();
85                 break;
86             }
87             case SET_INPUT_STREAM_DATA: {
88                 graph->SetInputStreamData(/*streamIndex =*/2, /* timestamp =*/0, /* data =*/"");
89                 break;
90             }
91             case SET_INPUT_STREAM_PIXEL_DATA: {
92                 runner::InputFrame inputFrame(0, 0, PixelFormat::RGB, 0, nullptr);
93                 graph->SetInputStreamPixelData(/*streamIndex =*/1, /*timestamp =*/0,
94                                                /*inputFrame =*/inputFrame);
95                 break;
96             }
97             case START_GRAPH_PROFILING: {
98                 graph->StartGraphProfiling();
99                 break;
100             }
101             case STOP_GRAPH_PROFILING: {
102                 graph->StopGraphProfiling();
103                 break;
104             }
105             case HANDLE_CONFIG_PHASE: {
106                 std::map<int, int> maxOutputPacketsPerStream;
107                 ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
108                 e.setPhaseState(runner::PhaseState::ENTRY);
109                 graph->handleConfigPhase(e);
110                 break;
111             }
112             case HANDLE_EXECUTION_PHASE: {
113                 std::map<int, int> maxOutputPacketsPerStream;
114                 ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
115                 e.setPhaseState(runner::PhaseState::ENTRY);
116                 graph->handleExecutionPhase(e);
117                 break;
118             }
119             case HANDLE_STOP_IMMEDIATE_PHASE: {
120                 std::map<int, int> maxOutputPacketsPerStream;
121                 ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
122                 e.setPhaseState(runner::PhaseState::ENTRY);
123                 graph->handleStopImmediatePhase(e);
124                 break;
125             }
126             case HANDLE_STOP_WITH_FLUSH_PHASE: {
127                 std::map<int, int> maxOutputPacketsPerStream;
128                 ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
129                 e.setPhaseState(runner::PhaseState::ENTRY);
130                 graph->handleStopWithFlushPhase(e);
131                 break;
132             }
133             case HANDLE_RESET_PHASE: {
134                 std::map<int, int> maxOutputPacketsPerStream;
135                 ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
136                 e.setPhaseState(runner::PhaseState::ENTRY);
137                 graph->handleResetPhase(e);
138                 break;
139             }
140             case DISPATCH_PIXEL_DATA: {
141                 runner::InputFrame inputFrame(0, 0, PixelFormat::RGB, 0, nullptr);
142                 graph->dispatchPixelData(/*streamIndex =*/2, /*timestamp =*/0,
143                                          /*inputFrame =*/inputFrame);
144                 break;
145             }
146             case DISPATCH_SERIALIZED_DATA: {
147                 graph->dispatchSerializedData(/*streamIndex =*/1, /* timestamp =*/0, /* data =*/"");
148                 break;
149             }
150             case DISPATCH_GRAPH_TERMINATION_MSG: {
151                 uint8_t status = fdp.ConsumeIntegralInRange<uint8_t>(0, Status::STATUS_MAX - 1);
152                 graph->dispatchGraphTerminationMessage(static_cast<Status>(status), "");
153                 break;
154             }
155             default:
156                 LOG(ERROR) << "Unexpected option aborting...";
157                 break;
158         }
159     }
160     return 0;
161 }
162 
163 }  // namespace
164 }  // namespace graph
165 }  // namespace computepipe
166 }  // namespace automotive
167 }  // namespace android
168