/* * 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 // For fd #include #include // For fd #include #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> a2dp_codec_operations = { // A2dpCodecs Constructor [](FuzzedDataProvider* fdp) -> void { // Build out a vector of codec objects std::vector codec_priorities; size_t num_priorities = fdp->ConsumeIntegralInRange(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& codec_priorities_const = codec_priorities; std::shared_ptr 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(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 codecs = getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); if (codecs) { a2dp_init_runs++; codecs->init(); } } }, // findSourceCodecConfig [](FuzzedDataProvider* fdp) -> void { std::shared_ptr 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 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 codecs = getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); if (codecs) { codecs->isSupportedCodec(getArbitraryBtavCodecIndex(fdp)); } }, // getCurrentCodecConfig [](FuzzedDataProvider* fdp) -> void { std::shared_ptr codecs = getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); if (codecs) { codecs->getCurrentCodecConfig(); } }, // orderedSourceCodecs [](FuzzedDataProvider* fdp) -> void { std::shared_ptr codecs = getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); if (codecs) { codecs->orderedSourceCodecs(); } }, // orderedSinkCodecs [](FuzzedDataProvider* fdp) -> void { std::shared_ptr codecs = getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); if (codecs) { codecs->orderedSinkCodecs(); } }, // setCodecConfig [](FuzzedDataProvider* fdp) -> void { std::shared_ptr 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 p_result_codec_config( reinterpret_cast(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 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 p_result_codec_config( reinterpret_cast(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 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(&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 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(&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 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(&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 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 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 codecs = getArbitraryVectorElement(fdp, a2dp_codecs_vect, false); if (codecs == nullptr) { return; } // Return objects std::vector codecs_local_capabilities; std::vector 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 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_