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 BT_STACK_FUZZ_A2DP_CODEC_FUNCTIONS_H_ 18 #define BT_STACK_FUZZ_A2DP_CODEC_FUNCTIONS_H_ 19 20 #include <fcntl.h> // For fd 21 #include <fuzzer/FuzzedDataProvider.h> 22 #include <sys/stat.h> // For fd 23 #include <vector> 24 #include "a2dp_codec_api.h" 25 #include "fuzzers/a2dp/codec/a2dpCodecHelperFunctions.h" 26 #include "fuzzers/a2dp/codec/a2dpCodecInfoFuzzFunctions.h" 27 #include "fuzzers/common/commonFuzzHelpers.h" 28 29 #include "fuzzers/a2dp/codec/a2dpCodecFuzzHelpers.h" 30 31 #define MAX_NUM_PROPERTIES 128 32 #define A2DP_MAX_INIT_RUNS 16 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 std::vector<std::function<void(FuzzedDataProvider*)>> a2dp_codec_operations = { 40 // A2dpCodecs Constructor 41 [](FuzzedDataProvider* fdp) -> void { 42 // Build out a vector of codec objects 43 std::vector<btav_a2dp_codec_config_t> codec_priorities; 44 size_t num_priorities = 45 fdp->ConsumeIntegralInRange<size_t>(0, MAX_NUM_PROPERTIES); 46 for (size_t i = 0; i < num_priorities; i++) { 47 codec_priorities.push_back(getArbitraryBtavCodecConfig(fdp)); 48 } 49 // Construct a const ref so we can pass to constructor 50 const std::vector<btav_a2dp_codec_config_t>& codec_priorities_const = 51 codec_priorities; 52 std::shared_ptr<A2dpCodecs> codecs( 53 new A2dpCodecs(codec_priorities_const)); 54 if (codecs) { 55 a2dp_codecs_vect.push_back(codecs); 56 } 57 }, 58 59 // A2dpCodecs Destructor 60 [](FuzzedDataProvider* fdp) -> void { 61 if (a2dp_codecs_vect.empty()) { 62 return; 63 } 64 // Get random vector index 65 size_t index = 66 fdp->ConsumeIntegralInRange<size_t>(0, a2dp_codecs_vect.size() - 1); 67 // Remove from vector 68 a2dp_codecs_vect.erase(a2dp_codecs_vect.begin() + index); 69 }, 70 71 // init 72 [](FuzzedDataProvider* fdp) -> void { 73 // Limit the number of times we can call this function per iteration 74 // (This is to prevent slow-units) 75 if (a2dp_init_runs <= A2DP_MAX_INIT_RUNS) { 76 std::shared_ptr<A2dpCodecs> codecs = 77 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 78 if (codecs) { 79 a2dp_init_runs++; 80 codecs->init(); 81 } 82 } 83 }, 84 85 // findSourceCodecConfig 86 [](FuzzedDataProvider* fdp) -> void { 87 std::shared_ptr<A2dpCodecs> codecs = 88 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 89 uint8_t* p_codec_info = 90 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 91 92 if (codecs && p_codec_info) { 93 codecs->findSourceCodecConfig(p_codec_info); 94 } 95 }, 96 97 // findSinkCodecConfig 98 [](FuzzedDataProvider* fdp) -> void { 99 std::shared_ptr<A2dpCodecs> codecs = 100 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 101 uint8_t* p_codec_info = 102 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 103 104 if (codecs && p_codec_info) { 105 codecs->findSinkCodecConfig(p_codec_info); 106 } 107 }, 108 109 // isSupportedCodec 110 [](FuzzedDataProvider* fdp) -> void { 111 std::shared_ptr<A2dpCodecs> codecs = 112 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 113 if (codecs) { 114 codecs->isSupportedCodec(getArbitraryBtavCodecIndex(fdp)); 115 } 116 }, 117 118 // getCurrentCodecConfig 119 [](FuzzedDataProvider* fdp) -> void { 120 std::shared_ptr<A2dpCodecs> codecs = 121 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 122 if (codecs) { 123 codecs->getCurrentCodecConfig(); 124 } 125 }, 126 127 // orderedSourceCodecs 128 [](FuzzedDataProvider* fdp) -> void { 129 std::shared_ptr<A2dpCodecs> codecs = 130 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 131 if (codecs) { 132 codecs->orderedSourceCodecs(); 133 } 134 }, 135 136 // orderedSinkCodecs 137 [](FuzzedDataProvider* fdp) -> void { 138 std::shared_ptr<A2dpCodecs> codecs = 139 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 140 if (codecs) { 141 codecs->orderedSinkCodecs(); 142 } 143 }, 144 145 // setCodecConfig 146 [](FuzzedDataProvider* fdp) -> void { 147 std::shared_ptr<A2dpCodecs> codecs = 148 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 149 if (codecs == nullptr) { 150 return; 151 } 152 153 const uint8_t* peer_codec_info = 154 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 155 if (peer_codec_info == nullptr) { 156 return; 157 } 158 159 // Codec_config is actually some buffer 160 std::unique_ptr<uint8_t, void (*)(void*)> p_result_codec_config( 161 reinterpret_cast<uint8_t*>(calloc(500, sizeof(uint8_t))), free); 162 if (p_result_codec_config) { 163 codecs->setCodecConfig(peer_codec_info, fdp->ConsumeBool(), 164 p_result_codec_config.get(), fdp->ConsumeBool()); 165 } 166 }, 167 168 // setSinkCodecConfig 169 [](FuzzedDataProvider* fdp) -> void { 170 std::shared_ptr<A2dpCodecs> codecs = 171 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 172 if (codecs == nullptr) { 173 return; 174 } 175 176 const uint8_t* peer_codec_info = 177 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 178 if (peer_codec_info == nullptr) { 179 return; 180 } 181 182 // Codec_config is actually some buffer 183 std::unique_ptr<uint8_t, void (*)(void*)> p_result_codec_config( 184 reinterpret_cast<uint8_t*>(calloc(500, sizeof(uint8_t))), free); 185 if (p_result_codec_config) { 186 codecs->setSinkCodecConfig(peer_codec_info, fdp->ConsumeBool(), 187 p_result_codec_config.get(), 188 fdp->ConsumeBool()); 189 } 190 }, 191 192 // setCodecUserConfig 193 [](FuzzedDataProvider* fdp) -> void { 194 std::shared_ptr<A2dpCodecs> codecs = 195 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 196 if (codecs == nullptr) { 197 return; 198 } 199 200 const btav_a2dp_codec_config_t codec_user_config = 201 getArbitraryBtavCodecConfig(fdp); 202 const tA2DP_ENCODER_INIT_PEER_PARAMS p_peer_params = 203 getArbitraryA2dpEncoderInitPeerParams(fdp); 204 const uint8_t* p_peer_sink_capabilities = 205 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 206 if (p_peer_sink_capabilities == nullptr) { 207 return; 208 } 209 210 // Craft our result variables (And possibly pass nullptrs) 211 btav_a2dp_codec_config_t result_codec_config; 212 bool restart_input, restart_output, config_updated; 213 uint8_t* p_result_codec_config = 214 reinterpret_cast<uint8_t*>(&result_codec_config); 215 codecs->setCodecUserConfig(codec_user_config, &p_peer_params, 216 p_peer_sink_capabilities, 217 p_result_codec_config, &restart_input, 218 &restart_output, &config_updated); 219 }, 220 221 // setCodecAudioConfig 222 [](FuzzedDataProvider* fdp) -> void { 223 std::shared_ptr<A2dpCodecs> codecs = 224 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 225 if (codecs == nullptr) { 226 return; 227 } 228 229 const btav_a2dp_codec_config_t codec_audio_config = 230 getArbitraryBtavCodecConfig(fdp); 231 const tA2DP_ENCODER_INIT_PEER_PARAMS p_peer_params = 232 getArbitraryA2dpEncoderInitPeerParams(fdp); 233 const uint8_t* p_peer_sink_capabilities = 234 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 235 if (p_peer_sink_capabilities == nullptr) { 236 return; 237 } 238 btav_a2dp_codec_config_t result_codec_config; 239 uint8_t* p_result_codec_config = 240 reinterpret_cast<uint8_t*>(&result_codec_config); 241 bool p_restart_output, p_config_updated; 242 codecs->setCodecAudioConfig( 243 codec_audio_config, &p_peer_params, p_peer_sink_capabilities, 244 p_result_codec_config, &p_restart_output, &p_config_updated); 245 }, 246 247 // setCodecOtaConfig 248 [](FuzzedDataProvider* fdp) -> void { 249 std::shared_ptr<A2dpCodecs> codecs = 250 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 251 if (codecs == nullptr) { 252 return; 253 } 254 255 const uint8_t* p_ota_codec_config = 256 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 257 if (p_ota_codec_config == nullptr) { 258 return; 259 } 260 261 const tA2DP_ENCODER_INIT_PEER_PARAMS p_peer_params = 262 getArbitraryA2dpEncoderInitPeerParams(fdp); 263 btav_a2dp_codec_config_t result_codec_config; 264 uint8_t* p_result_codec_config = 265 reinterpret_cast<uint8_t*>(&result_codec_config); 266 bool p_restart_input, p_restart_output, p_config_updated; 267 codecs->setCodecOtaConfig(p_ota_codec_config, &p_peer_params, 268 p_result_codec_config, &p_restart_input, 269 &p_restart_output, &p_config_updated); 270 }, 271 272 // setPeerSinkCodecCapabilities 273 [](FuzzedDataProvider* fdp) -> void { 274 std::shared_ptr<A2dpCodecs> codecs = 275 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 276 if (codecs == nullptr) { 277 return; 278 } 279 280 const uint8_t* p_peer_codec_capabilities = 281 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 282 if (p_peer_codec_capabilities == nullptr) { 283 return; 284 } 285 codecs->setPeerSinkCodecCapabilities(p_peer_codec_capabilities); 286 }, 287 288 // setPeerSourceCodecCapabilities 289 [](FuzzedDataProvider* fdp) -> void { 290 std::shared_ptr<A2dpCodecs> codecs = 291 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 292 if (codecs == nullptr) { 293 return; 294 } 295 296 const uint8_t* p_peer_codec_capabilities = 297 getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); 298 if (p_peer_codec_capabilities == nullptr) { 299 return; 300 } 301 codecs->setPeerSourceCodecCapabilities(p_peer_codec_capabilities); 302 }, 303 304 // getCodecConfigAndCapabilities 305 [](FuzzedDataProvider* fdp) -> void { 306 std::shared_ptr<A2dpCodecs> codecs = 307 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 308 if (codecs == nullptr) { 309 return; 310 } 311 312 // Return objects 313 std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities; 314 std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities; 315 btav_a2dp_codec_config_t codec_config; 316 codecs->getCodecConfigAndCapabilities(&codec_config, 317 &codecs_local_capabilities, 318 &codecs_selectable_capabilities); 319 }, 320 321 // debug_codec_dump 322 [](FuzzedDataProvider* fdp) -> void { 323 std::shared_ptr<A2dpCodecs> codecs = 324 getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); 325 if (codecs == nullptr) { 326 return; 327 } 328 329 // Dump this to /dev/null 330 int fd = open("/dev/null", O_WRONLY); 331 codecs->debug_codec_dump(fd); 332 close(fd); 333 }, 334 335 // Since we're dependent on having valid codec_info objects, 336 // have a change to call fuzz functions for that 337 [](FuzzedDataProvider* fdp) -> void { 338 callArbitraryCodecInfoFunction(fdp, a2dp_codec_info_operations); 339 }}; 340 341 #endif // BT_STACK_FUZZ_A2DP_CODEC_FUNCTIONS_H_ 342