| /* |
| * Copyright 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef BT_STACK_FUZZ_A2DP_CODEC_FUNCTIONS_H_ |
| #define BT_STACK_FUZZ_A2DP_CODEC_FUNCTIONS_H_ |
| |
| #include <fcntl.h> // For fd |
| #include <fuzzer/FuzzedDataProvider.h> |
| #include <sys/stat.h> // For fd |
| #include <vector> |
| #include "a2dp_codec_api.h" |
| #include "fuzzers/a2dp/codec/a2dpCodecHelperFunctions.h" |
| #include "fuzzers/a2dp/codec/a2dpCodecInfoFuzzFunctions.h" |
| #include "fuzzers/common/commonFuzzHelpers.h" |
| |
| #include "fuzzers/a2dp/codec/a2dpCodecFuzzHelpers.h" |
| |
| #define MAX_NUM_PROPERTIES 128 |
| #define A2DP_MAX_INIT_RUNS 16 |
| |
| /* This is a vector of lambda functions the fuzzer will pull from. |
| * This is done so new functions can be added to the fuzzer easily |
| * without requiring modifications to the main fuzzer file. This also |
| * allows multiple fuzzers to include this file, if functionality is needed. |
| */ |
| std::vector<std::function<void(FuzzedDataProvider*)>> a2dp_codec_operations = { |
| // A2dpCodecs Constructor |
| [](FuzzedDataProvider* fdp) -> void { |
| // Build out a vector of codec objects |
| std::vector<btav_a2dp_codec_config_t> codec_priorities; |
| size_t num_priorities = |
| fdp->ConsumeIntegralInRange<size_t>(0, MAX_NUM_PROPERTIES); |
| for (size_t i = 0; i < num_priorities; i++) { |
| codec_priorities.push_back(getArbitraryBtavCodecConfig(fdp)); |
| } |
| // Construct a const ref so we can pass to constructor |
| const std::vector<btav_a2dp_codec_config_t>& codec_priorities_const = |
| codec_priorities; |
| std::shared_ptr<A2dpCodecs> codecs( |
| new A2dpCodecs(codec_priorities_const)); |
| if (codecs) { |
| a2dp_codecs_vect.push_back(codecs); |
| } |
| }, |
| |
| // A2dpCodecs Destructor |
| [](FuzzedDataProvider* fdp) -> void { |
| if (a2dp_codecs_vect.empty()) { |
| return; |
| } |
| // Get random vector index |
| size_t index = |
| fdp->ConsumeIntegralInRange<size_t>(0, a2dp_codecs_vect.size() - 1); |
| // Remove from vector |
| a2dp_codecs_vect.erase(a2dp_codecs_vect.begin() + index); |
| }, |
| |
| // init |
| [](FuzzedDataProvider* fdp) -> void { |
| // Limit the number of times we can call this function per iteration |
| // (This is to prevent slow-units) |
| if (a2dp_init_runs <= A2DP_MAX_INIT_RUNS) { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs) { |
| a2dp_init_runs++; |
| codecs->init(); |
| } |
| } |
| }, |
| |
| // findSourceCodecConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| uint8_t* p_codec_info = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| |
| if (codecs && p_codec_info) { |
| codecs->findSourceCodecConfig(p_codec_info); |
| } |
| }, |
| |
| // findSinkCodecConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| uint8_t* p_codec_info = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| |
| if (codecs && p_codec_info) { |
| codecs->findSinkCodecConfig(p_codec_info); |
| } |
| }, |
| |
| // isSupportedCodec |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs) { |
| codecs->isSupportedCodec(getArbitraryBtavCodecIndex(fdp)); |
| } |
| }, |
| |
| // getCurrentCodecConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs) { |
| codecs->getCurrentCodecConfig(); |
| } |
| }, |
| |
| // orderedSourceCodecs |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs) { |
| codecs->orderedSourceCodecs(); |
| } |
| }, |
| |
| // orderedSinkCodecs |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs) { |
| codecs->orderedSinkCodecs(); |
| } |
| }, |
| |
| // setCodecConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| const uint8_t* peer_codec_info = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| if (peer_codec_info == nullptr) { |
| return; |
| } |
| |
| // Codec_config is actually some buffer |
| std::unique_ptr<uint8_t, void (*)(void*)> p_result_codec_config( |
| reinterpret_cast<uint8_t*>(calloc(500, sizeof(uint8_t))), free); |
| if (p_result_codec_config) { |
| codecs->setCodecConfig(peer_codec_info, fdp->ConsumeBool(), |
| p_result_codec_config.get(), fdp->ConsumeBool()); |
| } |
| }, |
| |
| // setSinkCodecConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| const uint8_t* peer_codec_info = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| if (peer_codec_info == nullptr) { |
| return; |
| } |
| |
| // Codec_config is actually some buffer |
| std::unique_ptr<uint8_t, void (*)(void*)> p_result_codec_config( |
| reinterpret_cast<uint8_t*>(calloc(500, sizeof(uint8_t))), free); |
| if (p_result_codec_config) { |
| codecs->setSinkCodecConfig(peer_codec_info, fdp->ConsumeBool(), |
| p_result_codec_config.get(), |
| fdp->ConsumeBool()); |
| } |
| }, |
| |
| // setCodecUserConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| const btav_a2dp_codec_config_t codec_user_config = |
| getArbitraryBtavCodecConfig(fdp); |
| const tA2DP_ENCODER_INIT_PEER_PARAMS p_peer_params = |
| getArbitraryA2dpEncoderInitPeerParams(fdp); |
| const uint8_t* p_peer_sink_capabilities = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| if (p_peer_sink_capabilities == nullptr) { |
| return; |
| } |
| |
| // Craft our result variables (And possibly pass nullptrs) |
| btav_a2dp_codec_config_t result_codec_config; |
| bool restart_input, restart_output, config_updated; |
| uint8_t* p_result_codec_config = |
| reinterpret_cast<uint8_t*>(&result_codec_config); |
| codecs->setCodecUserConfig(codec_user_config, &p_peer_params, |
| p_peer_sink_capabilities, |
| p_result_codec_config, &restart_input, |
| &restart_output, &config_updated); |
| }, |
| |
| // setCodecAudioConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| const btav_a2dp_codec_config_t codec_audio_config = |
| getArbitraryBtavCodecConfig(fdp); |
| const tA2DP_ENCODER_INIT_PEER_PARAMS p_peer_params = |
| getArbitraryA2dpEncoderInitPeerParams(fdp); |
| const uint8_t* p_peer_sink_capabilities = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| if (p_peer_sink_capabilities == nullptr) { |
| return; |
| } |
| btav_a2dp_codec_config_t result_codec_config; |
| uint8_t* p_result_codec_config = |
| reinterpret_cast<uint8_t*>(&result_codec_config); |
| bool p_restart_output, p_config_updated; |
| codecs->setCodecAudioConfig( |
| codec_audio_config, &p_peer_params, p_peer_sink_capabilities, |
| p_result_codec_config, &p_restart_output, &p_config_updated); |
| }, |
| |
| // setCodecOtaConfig |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| const uint8_t* p_ota_codec_config = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| if (p_ota_codec_config == nullptr) { |
| return; |
| } |
| |
| const tA2DP_ENCODER_INIT_PEER_PARAMS p_peer_params = |
| getArbitraryA2dpEncoderInitPeerParams(fdp); |
| btav_a2dp_codec_config_t result_codec_config; |
| uint8_t* p_result_codec_config = |
| reinterpret_cast<uint8_t*>(&result_codec_config); |
| bool p_restart_input, p_restart_output, p_config_updated; |
| codecs->setCodecOtaConfig(p_ota_codec_config, &p_peer_params, |
| p_result_codec_config, &p_restart_input, |
| &p_restart_output, &p_config_updated); |
| }, |
| |
| // setPeerSinkCodecCapabilities |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| const uint8_t* p_peer_codec_capabilities = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| if (p_peer_codec_capabilities == nullptr) { |
| return; |
| } |
| codecs->setPeerSinkCodecCapabilities(p_peer_codec_capabilities); |
| }, |
| |
| // setPeerSourceCodecCapabilities |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| const uint8_t* p_peer_codec_capabilities = |
| getArbitraryVectorElement(fdp, a2dp_codec_info_vect, false); |
| if (p_peer_codec_capabilities == nullptr) { |
| return; |
| } |
| codecs->setPeerSourceCodecCapabilities(p_peer_codec_capabilities); |
| }, |
| |
| // getCodecConfigAndCapabilities |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| // Return objects |
| std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities; |
| std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities; |
| btav_a2dp_codec_config_t codec_config; |
| codecs->getCodecConfigAndCapabilities(&codec_config, |
| &codecs_local_capabilities, |
| &codecs_selectable_capabilities); |
| }, |
| |
| // debug_codec_dump |
| [](FuzzedDataProvider* fdp) -> void { |
| std::shared_ptr<A2dpCodecs> codecs = |
| getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); |
| if (codecs == nullptr) { |
| return; |
| } |
| |
| // Dump this to /dev/null |
| int fd = open("/dev/null", O_WRONLY); |
| codecs->debug_codec_dump(fd); |
| close(fd); |
| }, |
| |
| // Since we're dependent on having valid codec_info objects, |
| // have a change to call fuzz functions for that |
| [](FuzzedDataProvider* fdp) -> void { |
| callArbitraryCodecInfoFunction(fdp, a2dp_codec_info_operations); |
| }}; |
| |
| #endif // BT_STACK_FUZZ_A2DP_CODEC_FUNCTIONS_H_ |