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