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 #ifndef FUZZER_SDP_FUNCTIONS_H_
18 #define FUZZER_SDP_FUNCTIONS_H_
19 
20 #include <base/functional/bind.h>
21 #include <fuzzer/FuzzedDataProvider.h>
22 
23 #include <vector>
24 
25 #include "fuzzers/common/commonFuzzHelpers.h"
26 #include "fuzzers/sdp/sdpFuzzHelpers.h"
27 #include "stack/include/sdp_api.h"
28 #include "types/bluetooth/uuid.h"
29 #include "types/raw_address.h"
30 
31 #define SDP_MAX_DB_LEN 1024 * 1024  // 1 MB
32 #define MAX_NUM_DBS 64
33 
34 /* This is a vector of lambda functions the fuzzer will pull from.
35  *  This is done so new functions can be added to the fuzzer easily
36  *  without requiring modifications to the main fuzzer file. This also
37  *  allows multiple fuzzers to include this file, if functionality is needed.
38  */
39 static const std::vector<std::function<void(FuzzedDataProvider*)>> sdp_operations = {
40         // ::SDP_InitDiscoveryDb
41         [](FuzzedDataProvider* fdp) -> void {
42           if (sdp_db_vect.size() >= MAX_NUM_DBS) {
43             return;
44           }
45 
46           // build out uuid_list
47           std::vector<bluetooth::Uuid> uuid_list;
48           uint8_t num_uuids = fdp->ConsumeIntegral<uint8_t>();
49           for (uint8_t i = 0; i < num_uuids; i++) {
50             uuid_list.push_back(generateArbitraryUuid(fdp));
51           }
52 
53           // build out attr_list
54           std::vector<uint16_t> attr_list = generateArbitraryAttrList(fdp);
55 
56           uint32_t db_size = fdp->ConsumeIntegralInRange<uint32_t>(0, SDP_MAX_DB_LEN);
57           std::shared_ptr<tSDP_DISCOVERY_DB> p_db(
58                   reinterpret_cast<tSDP_DISCOVERY_DB*>(malloc(db_size)), free);
59           if (p_db) {
60             bool success = get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
61                     p_db.get(), db_size, uuid_list.size(), uuid_list.data(), attr_list.size(),
62                     reinterpret_cast<uint16_t*>(attr_list.data()));
63             if (success) {
64               sdp_db_vect.push_back(p_db);
65             }
66           }
67         },
68 
69         // ::SDP_CancelServiceSearch
70         [](FuzzedDataProvider* fdp) -> void {
71           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->service.SDP_CancelServiceSearch(
72                   getArbitraryVectorElement(fdp, sdp_db_vect, true).get());
73         },
74 
75         // ::SDP_ServiceSearchRequest
76         [](FuzzedDataProvider* fdp) -> void {
77           const RawAddress bd_addr = generateRawAddress(fdp);
78           tSDP_DISCOVERY_DB* db = getArbitraryVectorElement(fdp, sdp_db_vect, false).get();
79           if (db) {
80             [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->service.SDP_ServiceSearchRequest(
81                     bd_addr, db, &sdp_disc_cmpl_cb);
82           }
83         },
84 
85         // ::SDP_ServiceSearchAttributeRequest
86         [](FuzzedDataProvider* fdp) -> void {
87           const RawAddress bd_addr = generateRawAddress(fdp);
88           tSDP_DISCOVERY_DB* db = getArbitraryVectorElement(fdp, sdp_db_vect, false).get();
89           if (db) {
90             [[maybe_unused]] bool rc =
91                     get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest(
92                             bd_addr, db, &sdp_disc_cmpl_cb);
93           }
94         },
95 
96         // ::SDP_ServiceSearchAttributeRequest2
97         [](FuzzedDataProvider* fdp) -> void {
98           const RawAddress bd_addr = generateRawAddress(fdp);
99           std::vector<uint8_t> user_data =
100                   fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(0, 1024));
101           tSDP_DISCOVERY_DB* db = getArbitraryVectorElement(fdp, sdp_db_vect, false).get();
102 
103           if (db) {
104             [[maybe_unused]] bool rc =
105                     get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest2(
106                             bd_addr, db, base::BindRepeating(&sdp_disc_cmpl_cb2, user_data));
107           }
108         },
109 
110         // ::SDP_FindAttributeInRec
111         [](FuzzedDataProvider* fdp) -> void {
112           tSDP_DISC_REC* p_rec = generateArbitrarySdpDiscRecord(fdp, false).get();
113           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(
114                   p_rec, fdp->ConsumeIntegral<uint16_t>());
115         },
116 
117         // ::SDP_FindServiceInDb
118         [](FuzzedDataProvider* fdp) -> void {
119           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb(
120                   getArbitraryVectorElement(fdp, sdp_db_vect, true).get(),
121                   fdp->ConsumeIntegral<uint16_t>(),
122                   generateArbitrarySdpDiscRecord(fdp, true).get());
123         },
124 
125         // ::SDP_FindServiceUUIDInDb
126         [](FuzzedDataProvider* fdp) -> void {
127           const bluetooth::Uuid uuid = generateArbitraryUuid(fdp);
128           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->db.SDP_FindServiceUUIDInDb(
129                   getArbitraryVectorElement(fdp, sdp_db_vect, true).get(), uuid,
130                   generateArbitrarySdpDiscRecord(fdp, true).get());
131         },
132 
133         // ::SDP_FindServiceUUIDInRec_128bit
134         [](FuzzedDataProvider* fdp) -> void {
135           bluetooth::Uuid uuid = generateArbitraryUuid(fdp);
136           tSDP_DISC_REC* p_rec = generateArbitrarySdpDiscRecord(fdp, false).get();
137           [[maybe_unused]] bool rc =
138                   get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec_128bit(p_rec, &uuid);
139         },
140 
141         // ::SDP_FindServiceInDb_128bit
142         [](FuzzedDataProvider* fdp) -> void {
143           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb_128bit(
144                   getArbitraryVectorElement(fdp, sdp_db_vect, true).get(),
145                   generateArbitrarySdpDiscRecord(fdp, true).get());
146         },
147 
148         // ::SDP_FindProtocolListElemInRec
149         [](FuzzedDataProvider* fdp) -> void {
150           tSDP_PROTOCOL_ELEM elem = generateArbitrarySdpProtocolElements(fdp);
151           tSDP_DISC_REC* p_rec = generateArbitrarySdpDiscRecord(fdp, false).get();
152           [[maybe_unused]] bool rc =
153                   get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec(
154                           p_rec, fdp->ConsumeIntegral<uint16_t>(), &elem);
155         },
156 
157         // ::SDP_FindProfileVersionInRec
158         [](FuzzedDataProvider* fdp) -> void {
159           uint16_t p_version;
160           tSDP_DISC_REC* p_rec = generateArbitrarySdpDiscRecord(fdp, false).get();
161 
162           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->record.SDP_FindProfileVersionInRec(
163                   p_rec, fdp->ConsumeIntegral<uint16_t>(), &p_version);
164         },
165 
166         // ::SDP_CreateRecord
167         [](FuzzedDataProvider* /*fdp*/) -> void {
168           uint32_t handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
169           if (handle) {
170             sdp_record_handles.push_back(handle);
171           }
172         },
173 
174         // ::SDP_DeleteRecord
175         [](FuzzedDataProvider* fdp) -> void {
176           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(
177                   getArbitraryVectorElement(fdp, sdp_record_handles, true));
178         },
179 
180         // ::SDP_AddAttribute
181         [](FuzzedDataProvider* fdp) -> void {
182           std::vector<uint8_t> val =
183                   fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(1, 1024));
184           if (val.size() > 0) {
185             [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
186                     getArbitraryVectorElement(fdp, sdp_record_handles, true),
187                     fdp->ConsumeIntegral<uint16_t>(), fdp->ConsumeIntegral<uint8_t>(), val.size(),
188                     val.data());
189           }
190         },
191 
192         // ::SDP_AddSequence
193         [](FuzzedDataProvider* fdp) -> void {
194           SDP_Sequence_Helper seq = generateArbitrarySdpElemSequence(fdp);
195 
196           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->handle.SDP_AddSequence(
197                   getArbitraryVectorElement(fdp, sdp_record_handles, true),
198                   fdp->ConsumeIntegral<uint16_t>(), seq.num_elem, seq.type.get(), seq.len.get(),
199                   seq.p_val.get());
200         },
201 
202         // ::SDP_AddUuidSequence
203         [](FuzzedDataProvider* fdp) -> void {
204           uint16_t num_uuids = fdp->ConsumeIntegralInRange<uint16_t>(1, 64);
205           uint16_t* uuids = new uint16_t[num_uuids];
206           for (uint16_t i = 0; i < num_uuids; i++) {
207             uuids[i] = fdp->ConsumeIntegral<uint16_t>();
208           }
209 
210           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
211                   getArbitraryVectorElement(fdp, sdp_record_handles, true),
212                   fdp->ConsumeIntegral<uint16_t>(), num_uuids, uuids);
213           delete[] uuids;
214         },
215 
216         // ::SDP_AddProtocolList
217         [](FuzzedDataProvider* fdp) -> void {
218           std::shared_ptr<tSDP_PROTO_LIST_ELEM> p_proto_list =
219                   generateArbitrarySdpProtocolElementList(fdp);
220           if (p_proto_list) {
221             [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
222                     getArbitraryVectorElement(fdp, sdp_record_handles, true),
223                     p_proto_list.get()->num_elems, p_proto_list.get()->list_elem);
224           }
225         },
226 
227         // ::SDP_AddAdditionProtoLists
228         [](FuzzedDataProvider* fdp) -> void {
229           uint16_t arr_size;
230           tSDP_PROTO_LIST_ELEM** p_proto_list =
231                   generateArbitrarySdpProtocolElementListArray(fdp, &arr_size);
232           if (p_proto_list) {
233             if (p_proto_list[0]) {
234               [[maybe_unused]] bool rc =
235                       get_legacy_stack_sdp_api()->handle.SDP_AddAdditionProtoLists(
236                               getArbitraryVectorElement(fdp, sdp_record_handles, true), arr_size,
237                               p_proto_list[0]);
238               for (uint16_t i = 0; i < arr_size; i++) {
239                 delete p_proto_list[i];
240               }
241             }
242             free(p_proto_list);
243           }
244         },
245 
246         // ::SDP_AddProfileDescriptorList
247         [](FuzzedDataProvider* fdp) -> void {
248           [[maybe_unused]] bool rc =
249                   get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
250                           getArbitraryVectorElement(fdp, sdp_record_handles, true),
251                           fdp->ConsumeIntegral<uint16_t>(), fdp->ConsumeIntegral<uint16_t>());
252         },
253 
254         // ::SDP_AddLanguageBaseAttrIDList
255         [](FuzzedDataProvider* fdp) -> void {
256           [[maybe_unused]] bool rc =
257                   get_legacy_stack_sdp_api()->handle.SDP_AddLanguageBaseAttrIDList(
258                           getArbitraryVectorElement(fdp, sdp_record_handles, true),
259                           fdp->ConsumeIntegral<uint16_t>(), fdp->ConsumeIntegral<uint16_t>(),
260                           fdp->ConsumeIntegral<uint16_t>());
261         },
262 
263         // ::SDP_AddServiceClassIdList
264         [](FuzzedDataProvider* fdp) -> void {
265           uint16_t num_services = fdp->ConsumeIntegralInRange<uint16_t>(0, 64);
266           uint16_t* service_uuids = new uint16_t[num_services];
267           for (uint16_t i = 0; i < num_services; i++) {
268             service_uuids[i] = fdp->ConsumeIntegral<uint16_t>();
269           }
270 
271           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
272                   getArbitraryVectorElement(fdp, sdp_record_handles, true), num_services,
273                   service_uuids);
274 
275           delete[] service_uuids;
276         },
277 
278         // ::SDP_SetLocalDiRecord
279         [](FuzzedDataProvider* fdp) -> void {
280           uint32_t handle;  // Output var
281           tSDP_DI_RECORD device_info = generateArbitrarySdpDiRecord(fdp);
282           [[maybe_unused]] tSDP_STATUS rc =
283                   get_legacy_stack_sdp_api()->device_id.SDP_SetLocalDiRecord(&device_info, &handle);
284         },
285 
286         // ::SDP_DiDiscover
287         [](FuzzedDataProvider* fdp) -> void {
288           const RawAddress remote_device = generateRawAddress(fdp);
289 
290           // Create a new buffer for the discoveryDB init call
291           uint32_t db_size = fdp->ConsumeIntegralInRange<uint32_t>(0, SDP_MAX_DB_LEN);
292           std::shared_ptr<tSDP_DISCOVERY_DB> p_db(
293                   reinterpret_cast<tSDP_DISCOVERY_DB*>(malloc(db_size)), free);
294           if (p_db) {
295             [[maybe_unused]] tSDP_STATUS rc = get_legacy_stack_sdp_api()->device_id.SDP_DiDiscover(
296                     remote_device, p_db.get(), db_size, &sdp_disc_cmpl_cb);
297           }
298         },
299 
300         // ::SDP_GetNumDiRecords
301         [](FuzzedDataProvider* fdp) -> void {
302           [[maybe_unused]] bool rc = get_legacy_stack_sdp_api()->device_id.SDP_GetNumDiRecords(
303                   getArbitraryVectorElement(fdp, sdp_db_vect, true).get());
304         },
305 
306         // ::SDP_GetDiRecord
307         [](FuzzedDataProvider* fdp) -> void {
308           tSDP_DI_GET_RECORD device_info;  // Output var
309           [[maybe_unused]] tSDP_STATUS rc = get_legacy_stack_sdp_api()->device_id.SDP_GetDiRecord(
310                   fdp->ConsumeIntegral<uint8_t>(), &device_info,
311                   getArbitraryVectorElement(fdp, sdp_db_vect, true).get());
312         },
313 
314         // ::SDP_FindServiceUUIDInRec
315         [](FuzzedDataProvider* fdp) -> void {
316           tSDP_DISC_REC* p_rec = generateArbitrarySdpDiscRecord(fdp, false).get();
317           bluetooth::Uuid uuid;  // Output var
318           [[maybe_unused]] bool rc =
319                   get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec(p_rec, &uuid);
320         }};
321 
322 #endif  // FUZZER_SDP_FUNCTIONS_H_
323