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_HELPERS_H_
18 #define FUZZER_SDP_HELPERS_H_
19 
20 // NOTE: This file should not be included directly.
21 //       It is included by the corresponding "...Functions.h" file.
22 
23 #include <fuzzer/FuzzedDataProvider.h>
24 #include <algorithm>
25 #include <vector>
26 #include "fuzzers/common/commonFuzzHelpers.h"
27 #include "osi/include/alarm.h"
28 #include "stack/sdp/sdpint.h"
29 
30 #define SDP_MAX_NUM_ELEMS 128
31 #define SDP_MAX_ELEM_LEN 1024
32 #define SDP_MAX_ATTRS 1024
33 
34 struct SDP_Sequence_Helper {
35   uint8_t num_elem;
36   std::shared_ptr<uint8_t> type;
37   std::shared_ptr<uint8_t> len;
38   std::shared_ptr<uint8_t*> p_val;
39   std::vector<std::shared_ptr<uint8_t>> p_val_buffers;
40 };
41 
42 // Keep a vector of our initialized db objects
43 // It will be up to the caller to free this array at the end of a fuzz loop
44 std::vector<std::shared_ptr<tSDP_DISCOVERY_DB>> sdp_db_vect;
45 std::vector<uint32_t> sdp_record_handles;
46 std::vector<SDP_Sequence_Helper> sdp_sequence_vect;
47 std::vector<std::shared_ptr<tSDP_DISC_REC>> sdp_disc_rec_vect;
48 std::vector<std::shared_ptr<tSDP_DISC_ATTR>> sdp_disc_attr_vect;
49 std::vector<std::shared_ptr<tSDP_PROTO_LIST_ELEM>> sdp_protolist_elem_vect;
50 
51 std::shared_ptr<tSDP_DISC_ATTR> generateArbitrarySdpDiscAttr(
52     FuzzedDataProvider*, bool);
53 
54 static bool initialized = false;
setupSdpFuzz()55 void setupSdpFuzz() {
56   if (!initialized) {
57     sdp_init();
58     initialized = true;
59   }
60 }
61 
62 // Function to clean up and clear any allocated objects
cleanupSdpFuzz()63 void cleanupSdpFuzz() {
64   // Delete sdp_sequence_vect, sdp_disc_rec_vect, sdp_disc_attr_vect
65   sdp_sequence_vect.clear();
66 
67   sdp_disc_rec_vect.clear();
68 
69   // Delete attributes & protolist elements
70   sdp_disc_attr_vect.clear();
71   sdp_protolist_elem_vect.clear();
72 
73   // Delete all records
74   SDP_DeleteRecord(0);
75   sdp_record_handles.clear();
76 
77   // Delete Databases
78   sdp_db_vect.clear();
79 
80   // Set SDP Trace level back to default
81   SDP_SetTraceLevel(0);
82 }
83 
generateArbitraryAttrList(FuzzedDataProvider * fdp)84 std::vector<uint16_t> generateArbitraryAttrList(FuzzedDataProvider* fdp) {
85   // build out attr_list
86   uint16_t num_attrs = fdp->ConsumeIntegralInRange<uint16_t>(0, SDP_MAX_ATTRS);
87 
88   std::vector<uint16_t> attr_list;
89   for (uint16_t i = 0; i < num_attrs; i++) {
90     attr_list.push_back(fdp->ConsumeIntegral<uint16_t>());
91   }
92 
93   return attr_list;
94 }
95 
generateArbitrarySdpDiscAttrVal(FuzzedDataProvider * fdp)96 tSDP_DISC_ATVAL generateArbitrarySdpDiscAttrVal(FuzzedDataProvider* fdp) {
97   tSDP_DISC_ATVAL new_attrval;
98 
99   new_attrval.v.u8 = fdp->ConsumeIntegral<uint8_t>();
100   new_attrval.v.u16 = fdp->ConsumeIntegral<uint16_t>();
101   new_attrval.v.u32 = fdp->ConsumeIntegral<uint32_t>();
102   for (int i = 0; i < 4; i++) {
103     new_attrval.v.array[i] = fdp->ConsumeIntegral<uint8_t>();
104   }
105   new_attrval.v.p_sub_attr = generateArbitrarySdpDiscAttr(fdp, true).get();
106 
107   return new_attrval;
108 }
109 
generateArbitrarySdpDiscAttr(FuzzedDataProvider * fdp,bool allow_null)110 std::shared_ptr<tSDP_DISC_ATTR> generateArbitrarySdpDiscAttr(
111     FuzzedDataProvider* fdp, bool allow_null) {
112   // Give it a chance to return a nullptr
113   if (allow_null && !fdp->ConsumeBool()) {
114     return nullptr;
115   }
116 
117   std::shared_ptr<tSDP_DISC_ATTR> new_attr(new tSDP_DISC_ATTR);
118   sdp_disc_attr_vect.push_back(new_attr);
119 
120   new_attr->p_next_attr = generateArbitrarySdpDiscAttr(fdp, true).get();
121   new_attr->attr_id = fdp->ConsumeIntegral<uint16_t>();
122   new_attr->attr_len_type =
123       fdp->ConsumeBool() ? 16 : fdp->ConsumeIntegral<uint16_t>();
124   new_attr->attr_value = generateArbitrarySdpDiscAttrVal(fdp);
125 
126   return new_attr;
127 }
128 
generateArbitrarySdpDiscRecord(FuzzedDataProvider * fdp,bool allow_null)129 std::shared_ptr<tSDP_DISC_REC> generateArbitrarySdpDiscRecord(
130     FuzzedDataProvider* fdp, bool allow_null) {
131   // Give it a chance to return a nullptr
132   if (allow_null && !fdp->ConsumeBool()) {
133     return nullptr;
134   }
135 
136   std::shared_ptr<tSDP_DISC_REC> new_rec(new tSDP_DISC_REC);
137   sdp_disc_rec_vect.push_back(new_rec);
138 
139   new_rec->p_first_attr = generateArbitrarySdpDiscAttr(fdp, true).get();
140   new_rec->p_next_rec = generateArbitrarySdpDiscRecord(fdp, true).get();
141   new_rec->time_read = fdp->ConsumeIntegral<uint32_t>();
142   new_rec->remote_bd_addr = generateRawAddress(fdp);
143 
144   return new_rec;
145 }
146 
generateArbitrarySdpProtocolElements(FuzzedDataProvider * fdp)147 tSDP_PROTOCOL_ELEM generateArbitrarySdpProtocolElements(
148     FuzzedDataProvider* fdp) {
149   tSDP_PROTOCOL_ELEM p_elem;
150 
151   // Set our protocol element values
152   p_elem.protocol_uuid = fdp->ConsumeIntegral<uint16_t>();
153   p_elem.num_params =
154       fdp->ConsumeIntegralInRange<uint16_t>(0, SDP_MAX_PROTOCOL_PARAMS);
155   uint16_t num_loops = std::min(
156       p_elem.num_params, static_cast<unsigned short>(SDP_MAX_PROTOCOL_PARAMS));
157   // Regardless of number set above, fill out the entire allocated array
158   for (uint16_t i = 0; i < num_loops; i++) {
159     p_elem.params[i] = fdp->ConsumeIntegral<uint16_t>();
160   }
161 
162   return p_elem;
163 }
164 
generateArbitrarySdpProtocolElementList(FuzzedDataProvider * fdp)165 std::shared_ptr<tSDP_PROTO_LIST_ELEM> generateArbitrarySdpProtocolElementList(
166     FuzzedDataProvider* fdp) {
167   std::shared_ptr<tSDP_PROTO_LIST_ELEM> p_elem_list(new tSDP_PROTO_LIST_ELEM);
168   sdp_protolist_elem_vect.push_back(p_elem_list);
169 
170   // Populate our element list
171   p_elem_list->num_elems =
172       fdp->ConsumeIntegralInRange<uint16_t>(0, SDP_MAX_LIST_ELEMS);
173   uint16_t num_loops = std::min(
174       p_elem_list->num_elems, static_cast<unsigned short>(SDP_MAX_LIST_ELEMS));
175   for (uint16_t i = 0; i < num_loops; i++) {
176     p_elem_list->list_elem[i] = generateArbitrarySdpProtocolElements(fdp);
177   }
178 
179   return p_elem_list;
180 }
181 
generateArbitrarySdpProtocolElementListArray(FuzzedDataProvider * fdp,uint16_t * array_size)182 tSDP_PROTO_LIST_ELEM** generateArbitrarySdpProtocolElementListArray(
183     FuzzedDataProvider* fdp, uint16_t* array_size) {
184   *array_size = fdp->ConsumeIntegralInRange<uint16_t>(0, SDP_MAX_ATTR_LEN);
185   if (*array_size == 0) {
186     return nullptr;
187   }
188   tSDP_PROTO_LIST_ELEM** p_list_array = static_cast<tSDP_PROTO_LIST_ELEM**>(
189       calloc(*array_size, sizeof(tSDP_PROTO_LIST_ELEM*)));
190   if (p_list_array == nullptr) {
191     return nullptr;
192   }
193 
194   tSDP_PROTO_LIST_ELEM* p = p_list_array[0];
195   for (uint16_t i = 0; i < *array_size; i++, p++) {
196     p = generateArbitrarySdpProtocolElementList(fdp).get();
197   }
198 
199   return p_list_array;
200 }
201 
generateArbitrarySdpDiRecord(FuzzedDataProvider * fdp)202 tSDP_DI_RECORD generateArbitrarySdpDiRecord(FuzzedDataProvider* fdp) {
203   tSDP_DI_RECORD record;
204 
205   record.vendor = fdp->ConsumeIntegral<uint16_t>();
206   record.vendor_id_source = fdp->ConsumeIntegral<uint16_t>();
207   record.product = fdp->ConsumeIntegral<uint16_t>();
208   record.version = fdp->ConsumeIntegral<uint16_t>();
209   record.primary_record = fdp->ConsumeBool();
210   size_t num_executable_urls =
211       fdp->ConsumeIntegralInRange<size_t>(0, SDP_MAX_ATTR_LEN);
212   for (size_t i = 0; i < num_executable_urls; i++) {
213     record.client_executable_url[i] = fdp->ConsumeIntegral<char>();
214   }
215   size_t num_descriptions =
216       fdp->ConsumeIntegralInRange<size_t>(0, SDP_MAX_ATTR_LEN);
217   for (size_t i = 0; i < num_descriptions; i++) {
218     record.service_description[i] = fdp->ConsumeIntegral<char>();
219   }
220   size_t num_documentation_urls =
221       fdp->ConsumeIntegralInRange<size_t>(0, SDP_MAX_ATTR_LEN);
222   for (size_t i = 0; i < num_documentation_urls; i++) {
223     record.documentation_url[i] = fdp->ConsumeIntegral<char>();
224   }
225 
226   return record;
227 }
228 
generateArbitrarySdpDiGetRecord(FuzzedDataProvider * fdp)229 tSDP_DI_GET_RECORD generateArbitrarySdpDiGetRecord(FuzzedDataProvider* fdp) {
230   tSDP_DI_GET_RECORD get_record;
231   get_record.spec_id = fdp->ConsumeIntegral<uint16_t>();
232   get_record.rec = generateArbitrarySdpDiRecord(fdp);
233 
234   return get_record;
235 }
236 
generateArbitrarySdpElemSequence(FuzzedDataProvider * fdp)237 SDP_Sequence_Helper generateArbitrarySdpElemSequence(FuzzedDataProvider* fdp) {
238   SDP_Sequence_Helper ret;
239 
240   // Get the number of our elements
241   ret.num_elem = fdp->ConsumeIntegralInRange<uint16_t>(1, SDP_MAX_NUM_ELEMS);
242   ret.type.reset(new uint8_t[ret.num_elem]);
243   ret.len.reset(new uint8_t[ret.num_elem]);
244   ret.p_val.reset(new uint8_t*[ret.num_elem]);
245   for (uint16_t i = 0; i < ret.num_elem; i++) {
246     (ret.type.get())[i] = fdp->ConsumeIntegral<uint8_t>();
247     if ((ret.len.get())[i] == 0) {
248       (ret.p_val.get())[i] = nullptr;
249       (ret.len.get())[i] = 0;
250     } else {
251       uint8_t buf_size = fdp->ConsumeIntegral<uint8_t>();
252       // Link the size to the size of the buffer we're creating
253       (ret.len.get())[i] = buf_size;
254       std::shared_ptr<uint8_t> p_val_sp(
255           reinterpret_cast<uint8_t*>(calloc(buf_size, sizeof(uint8_t))), free);
256       ret.p_val_buffers.push_back(p_val_sp);
257       (ret.p_val.get())[i] = p_val_sp.get();
258       std::vector<uint8_t> bytes = fdp->ConsumeBytes<uint8_t>(buf_size);
259       memcpy((ret.p_val.get())[i], bytes.data(), bytes.size());
260     }
261   }
262 
263   // Push this struct to our array so we can delete later
264   sdp_sequence_vect.push_back(ret);
265 
266   return ret;
267 }
268 
269 // Define our callback functions we'll be using within our functions
sdp_disc_cmpl_cb(tSDP_STATUS result)270 void sdp_disc_cmpl_cb(tSDP_STATUS result) {}
sdp_disc_cmpl_cb2(tSDP_STATUS result,void * user_data)271 void sdp_disc_cmpl_cb2(tSDP_STATUS result, void* user_data) {}
272 
273 #endif  // FUZZER_SDP_HELPERS_H_
274