1 /*
2  * Copyright 2022 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 <InputDevice.h>
18 #include <InputReaderBase.h>
19 #include <MapperHelpers.h>
20 #include <MultiTouchInputMapper.h>
21 
22 namespace android {
23 
24 const int32_t kMaxKeycodes = 100;
25 
addProperty(FuzzEventHub & eventHub,std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp)26 static void addProperty(FuzzEventHub& eventHub, std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) {
27     // Pick a random property to set for the mapper to have set.
28     fdp->PickValueInArray<std::function<void()>>(
29             {[&]() -> void { eventHub.addProperty("touch.deviceType", "touchScreen"); },
30              [&]() -> void {
31                  eventHub.addProperty("touch.deviceType", fdp->ConsumeRandomLengthString(8).data());
32              },
33              [&]() -> void {
34                  eventHub.addProperty("touch.size.scale", fdp->ConsumeRandomLengthString(8).data());
35              },
36              [&]() -> void {
37                  eventHub.addProperty("touch.size.bias", fdp->ConsumeRandomLengthString(8).data());
38              },
39              [&]() -> void {
40                  eventHub.addProperty("touch.size.isSummed",
41                                       fdp->ConsumeRandomLengthString(8).data());
42              },
43              [&]() -> void {
44                  eventHub.addProperty("touch.size.calibration",
45                                       fdp->ConsumeRandomLengthString(8).data());
46              },
47              [&]() -> void {
48                  eventHub.addProperty("touch.pressure.scale",
49                                       fdp->ConsumeRandomLengthString(8).data());
50              },
51              [&]() -> void {
52                  eventHub.addProperty("touch.size.calibration",
53                                       fdp->ConsumeBool() ? "diameter" : "area");
54              },
55              [&]() -> void {
56                  eventHub.addProperty("touch.pressure.calibration",
57                                       fdp->ConsumeRandomLengthString(8).data());
58              }})();
59 }
60 
LLVMFuzzerTestOneInput(uint8_t * data,size_t size)61 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
62     std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp =
63             std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
64 
65     // Create mocked objects to support the fuzzed input mapper.
66     std::shared_ptr<FuzzEventHub> eventHub = std::make_shared<FuzzEventHub>(fdp);
67     FuzzInputReaderContext context(eventHub, fdp);
68     InputDevice device = getFuzzedInputDevice(*fdp, &context);
69 
70     InputReaderConfiguration policyConfig;
71     MultiTouchInputMapper& mapper =
72             getMapperForDevice<ThreadSafeFuzzedDataProvider, MultiTouchInputMapper>(*fdp.get(),
73                                                                                     device,
74                                                                                     policyConfig);
75 
76     // Loop through mapper operations until randomness is exhausted.
77     while (fdp->remaining_bytes() > 0) {
78         fdp->PickValueInArray<std::function<void()>>({
79                 [&]() -> void {
80                     addProperty(*eventHub.get(), fdp);
81                     configureAndResetDevice(*fdp, device);
82                 },
83                 [&]() -> void {
84                     std::string dump;
85                     mapper.dump(dump);
86                 },
87                 [&]() -> void {
88                     InputDeviceInfo info;
89                     mapper.populateDeviceInfo(info);
90                 },
91                 [&]() -> void { mapper.getSources(); },
92                 [&]() -> void {
93                     std::list<NotifyArgs> unused =
94                             mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig,
95                                                InputReaderConfiguration::Change(
96                                                        fdp->ConsumeIntegral<uint32_t>()));
97                 },
98                 [&]() -> void {
99                     std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>());
100                 },
101                 [&]() -> void {
102                     RawEvent rawEvent = getFuzzedRawEvent(*fdp);
103                     std::list<NotifyArgs> unused = mapper.process(rawEvent);
104                 },
105                 [&]() -> void {
106                     mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(),
107                                            fdp->ConsumeIntegral<int32_t>());
108                 },
109                 [&]() -> void {
110                     mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(),
111                                             fdp->ConsumeIntegral<int32_t>());
112                 },
113                 [&]() -> void {
114                     std::vector<int32_t> keyCodes;
115                     int32_t numBytes = fdp->ConsumeIntegralInRange<int32_t>(0, kMaxKeycodes);
116                     for (int32_t i = 0; i < numBytes; ++i) {
117                         keyCodes.push_back(fdp->ConsumeIntegral<int32_t>());
118                     }
119                     mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(), keyCodes,
120                                                  nullptr);
121                 },
122                 [&]() -> void {
123                     std::list<NotifyArgs> unused =
124                             mapper.cancelTouch(fdp->ConsumeIntegral<nsecs_t>(),
125                                                fdp->ConsumeIntegral<nsecs_t>());
126                 },
127                 [&]() -> void {
128                     std::list<NotifyArgs> unused =
129                             mapper.timeoutExpired(fdp->ConsumeIntegral<nsecs_t>());
130                 },
131                 [&]() -> void {
132                     StylusState state{fdp->ConsumeIntegral<nsecs_t>(),
133                                       fdp->ConsumeFloatingPoint<float>(),
134                                       fdp->ConsumeIntegral<uint32_t>(), getFuzzedToolType(*fdp)};
135                     std::list<NotifyArgs> unused = mapper.updateExternalStylusState(state);
136                 },
137                 [&]() -> void { mapper.getAssociatedDisplayId(); },
138         })();
139     }
140 
141     return 0;
142 }
143 
144 } // namespace android
145