• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Common.h"
18 #include "DefaultEngine.h"
19 #include "VideoInputManager.h"
20 
21 #include <android-base/file.h>
22 #include <fuzzer/FuzzedDataProvider.h>
23 #include <gmock/gmock.h>
24 
25 #include <stdio.h>
26 #include <unistd.h>
27 
28 namespace android {
29 namespace automotive {
30 namespace computepipe {
31 namespace runner {
32 namespace input_manager {
33 
34 using android::base::Dirname;
35 
36 namespace {
37 
38 class MockRunnerEvent : public RunnerEvent {
39 public:
40     MOCK_CONST_METHOD0(isPhaseEntry, bool());
41     MOCK_CONST_METHOD0(isTransitionComplete, bool());
42     MOCK_CONST_METHOD0(isAborted, bool());
43     MOCK_METHOD1(dispatchToComponent,
44                  Status(const std::shared_ptr<RunnerComponentInterface>& iface));
45 };
46 
47 enum INPUT_MGR_FUZZ_FUNCS { RUNNER_COMP_BASE_ENUM };
48 
49 static std::shared_ptr<VideoInputManager> manager;
50 
LLVMFuzzerInitialize(int * argc,char *** argv)51 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
52     const std::string kFilename =
53             Dirname(*argv[0]) + "/data/corpus/video_input_manager/centaur_1.mpg";
54     if (access(kFilename.c_str(), F_OK) == -1) {
55         std::cerr << "Video file does not exist!" << std::endl;
56         exit(1);
57     }
58 
59     // Initialize input config
60     proto::InputConfig inputConf;
61     proto::InputStreamConfig* streamConfig = inputConf.add_input_stream();
62     proto::VideoFileConfig* videoConfig = streamConfig->mutable_video_config();
63     videoConfig->set_file_path(kFilename);
64 
65     // Initialize callBack, which does nothing
66     std::shared_ptr<InputEngineInterface> callBack = std::make_shared<engine::InputCallback>(
67             0, [](int i) {},
68             [](int i, int64_t j, const InputFrame& frame) { return Status::SUCCESS; });
69 
70     // Initialize manager
71     manager = std::make_shared<VideoInputManager>(inputConf, inputConf /* redundant */, callBack);
72     return 0;
73 }
74 
75 // TODO(b/163138279, b/163138595) verify the fix for these two bugs
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)76 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
77     FuzzedDataProvider fdp(data, size);
78     while (fdp.remaining_bytes() > test::kMaxFuzzerConsumedBytes) {
79         switch (fdp.ConsumeIntegralInRange<uint32_t>(0, API_SUM - 1)) {
80             case HANDLE_CONFIG_PHASE: {
81                 break;
82             }
83             case HANDLE_EXECUTION_PHASE: {
84                 testing::NiceMock<MockRunnerEvent> e;
85                 bool isTransitionComplete = fdp.ConsumeBool();
86                 bool isPhaseEntry = fdp.ConsumeBool();
87                 if (isTransitionComplete != isPhaseEntry) {
88                     if (isTransitionComplete) {
89                         EXPECT_CALL((e), isTransitionComplete()).WillOnce([isTransitionComplete]() {
90                             return isTransitionComplete;
91                         });
92                         ON_CALL((e), isPhaseEntry()).WillByDefault([isPhaseEntry]() {
93                             return isPhaseEntry;
94                         });
95                     } else if (isPhaseEntry) {
96                         ON_CALL((e), isTransitionComplete())
97                                 .WillByDefault(
98                                         [isTransitionComplete]() { return isTransitionComplete; });
99                         EXPECT_CALL((e), isPhaseEntry()).WillOnce([isPhaseEntry]() {
100                             return isPhaseEntry;
101                         });
102                     }
103                     Status res = manager->handleExecutionPhase(e);
104                     if (res == Status::SUCCESS && !isTransitionComplete && isPhaseEntry) {
105                         sleep(3);  // waiting for resource to be released
106                     } else {
107                         usleep(10);
108                     }
109                 }
110                 break;
111             }
112             case HANDLE_STOP_IMMEDIATE_PHASE: {
113                 testing::NiceMock<MockRunnerEvent> e;
114                 manager->handleStopImmediatePhase(e);
115                 break;
116             }
117             case HANDLE_STOP_WITH_FLUSH_PHASE: {
118                 testing::NiceMock<MockRunnerEvent> e;
119                 manager->handleStopWithFlushPhase(e);
120                 break;
121             }
122             case HANDLE_RESET_PHASE: {
123                 testing::NiceMock<MockRunnerEvent> e;
124                 manager->handleResetPhase(e);
125                 break;
126             }
127             default:
128                 LOG(ERROR) << "Unexpected option aborting...";
129                 break;
130         }
131     }
132     return 0;
133 }
134 
135 }  // namespace
136 }  // namespace input_manager
137 }  // namespace runner
138 }  // namespace computepipe
139 }  // namespace automotive
140 }  // namespace android
141