1 /*
2  * Copyright (C) 2024 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 
18 #include "device.h"
19 #include "fuzzer/FuzzedDataProvider.h"
20 #include "internal_include/stack_config.h"
21 #include "packet_test_helper.h"
22 #include "pass_through_packet.h"
23 
24 // TODO(b/369381361) Enfore -Wmissing-prototypes
25 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
26 
btif_av_src_sink_coexist_enabled(void)27 bool btif_av_src_sink_coexist_enabled(void) { return true; }
28 
29 namespace bluetooth {
30 namespace avrcp {
31 
32 static uint32_t kMinSize = 0;
33 static uint32_t kMaxSize = 10;
34 static uint32_t kMaxLen = 100;
35 static uint8_t kMinScope = 0;
36 static uint8_t kMaxScope = 3;
37 static uint8_t kMediaOpId = 0x44;
38 static uint8_t kMask = 0xFF;
39 static uint8_t k8BitShift = 8;
40 
41 const Opcode kValidOpCodes[] = {Opcode::VENDOR, Opcode::UNIT_INFO, Opcode::SUBUNIT_INFO,
42                                 Opcode::PASS_THROUGH};
43 
44 const CType kValidCTypes[] = {CType::CONTROL,         CType::STATUS,   CType::NOTIFY,
45                               CType::NOT_IMPLEMENTED, CType::ACCEPTED, CType::REJECTED,
46                               CType::STABLE,          CType::CHANGED,  CType::INTERIM};
47 
48 const BrowsePdu kPduVal[] = {BrowsePdu::SET_BROWSED_PLAYER,
49                              BrowsePdu::GET_FOLDER_ITEMS,
50                              BrowsePdu::CHANGE_PATH,
51                              BrowsePdu::GET_ITEM_ATTRIBUTES,
52                              BrowsePdu::GET_TOTAL_NUMBER_OF_ITEMS,
53                              BrowsePdu::GENERAL_REJECT};
54 
55 const CommandPdu kCommandPduVal[] = {CommandPdu::GET_CAPABILITIES,
56                                      CommandPdu::LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES,
57                                      CommandPdu::LIST_PLAYER_APPLICATION_SETTING_VALUES,
58                                      CommandPdu::GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE,
59                                      CommandPdu::SET_PLAYER_APPLICATION_SETTING_VALUE,
60                                      CommandPdu::GET_ELEMENT_ATTRIBUTES,
61                                      CommandPdu::GET_PLAY_STATUS,
62                                      CommandPdu::REGISTER_NOTIFICATION,
63                                      CommandPdu::SET_ABSOLUTE_VOLUME,
64                                      CommandPdu::SET_ADDRESSED_PLAYER,
65                                      CommandPdu::PLAY_ITEM};
66 
67 class FakeMediaInterface : public MediaInterface {
68 public:
FakeMediaInterface(FuzzedDataProvider * fdp)69   FakeMediaInterface(FuzzedDataProvider* fdp) : mFdp(fdp) {}
SendKeyEvent(uint8_t,KeyState)70   void SendKeyEvent(uint8_t /* key */, KeyState /* state */) { return; }
71   using SongInfoCallback = base::Callback<void(SongInfo)>;
GetSongInfo(SongInfoCallback info_cb)72   void GetSongInfo(SongInfoCallback info_cb) {
73     SongInfo sInfo;
74     sInfo.media_id = mFdp->ConsumeRandomLengthString(kMaxLen);
75     sInfo.attributes.insert(AttributeEntry(
76             Attribute(mFdp->ConsumeIntegralInRange<uint8_t>(uint8_t(Attribute::TITLE),
77                                                             uint8_t(Attribute::DEFAULT_COVER_ART))),
78             mFdp->ConsumeRandomLengthString(kMaxLen)));
79     info_cb.Run(sInfo);
80     return;
81   }
82   using PlayStatusCallback = base::Callback<void(PlayStatus)>;
GetPlayStatus(PlayStatusCallback status_cb)83   void GetPlayStatus(PlayStatusCallback status_cb) {
84     PlayStatus pst;
85     status_cb.Run(pst);
86     return;
87   }
88   using NowPlayingCallback = base::Callback<void(std::string, std::vector<SongInfo>)>;
GetNowPlayingList(NowPlayingCallback now_playing_cb)89   void GetNowPlayingList(NowPlayingCallback now_playing_cb) {
90     std::string currentSongId = mFdp->ConsumeRandomLengthString(kMaxLen);
91     size_t size = mFdp->ConsumeIntegralInRange<uint8_t>(kMinSize, kMaxSize);
92     std::vector<SongInfo> songInfoVec;
93     for (size_t iter = 0; iter < size; ++iter) {
94       SongInfo tempSongInfo;
95       tempSongInfo.media_id = mFdp->ConsumeRandomLengthString(kMaxLen);
96       tempSongInfo.attributes.insert(AttributeEntry(
97               Attribute(mFdp->ConsumeIntegralInRange<uint8_t>(
98                       uint8_t(Attribute::TITLE), uint8_t(Attribute::DEFAULT_COVER_ART))),
99               mFdp->ConsumeRandomLengthString(kMaxLen)));
100       songInfoVec.push_back(tempSongInfo);
101     }
102     now_playing_cb.Run(currentSongId, songInfoVec);
103     return;
104   }
105   using MediaListCallback =
106           base::Callback<void(uint16_t curr_player, std::vector<MediaPlayerInfo>)>;
GetMediaPlayerList(MediaListCallback list_cb)107   void GetMediaPlayerList(MediaListCallback list_cb) {
108     uint16_t currentPlayer = mFdp->ConsumeIntegral<uint16_t>();
109     size_t size = mFdp->ConsumeIntegralInRange<uint8_t>(kMinSize, kMaxSize);
110     std::vector<MediaPlayerInfo> playerList;
111     for (size_t iter = 0; iter < size; ++iter) {
112       MediaPlayerInfo tempInfo;
113       tempInfo.id = mFdp->ConsumeIntegral<uint16_t>();
114       tempInfo.name = mFdp->ConsumeRandomLengthString(kMaxLen);
115       tempInfo.browsing_supported = mFdp->ConsumeBool();
116       playerList.push_back(tempInfo);
117     }
118     list_cb.Run(currentPlayer, playerList);
119     return;
120   }
121   using FolderItemsCallback = base::Callback<void(std::vector<ListItem>)>;
GetFolderItems(uint16_t,std::string,FolderItemsCallback folder_cb)122   void GetFolderItems(uint16_t /* player_id */, std::string /* media_id */,
123                       FolderItemsCallback folder_cb) {
124     size_t size = mFdp->ConsumeIntegralInRange<uint8_t>(kMinSize, kMaxSize);
125     std::vector<ListItem> list;
126     for (size_t iter = 0; iter < size; ++iter) {
127       ListItem tempList;
128       tempList.type = mFdp->ConsumeBool() ? ListItem::FOLDER : ListItem::SONG;
129       tempList.folder.media_id = mFdp->ConsumeRandomLengthString(kMaxLen);
130       tempList.folder.name = mFdp->ConsumeRandomLengthString(kMaxLen);
131       tempList.folder.is_playable = mFdp->ConsumeBool();
132       tempList.song.media_id = mFdp->ConsumeRandomLengthString(kMaxLen);
133       tempList.song.attributes.insert(AttributeEntry(
134               Attribute(mFdp->ConsumeIntegralInRange<uint8_t>(
135                       uint8_t(Attribute::TITLE), uint8_t(Attribute::DEFAULT_COVER_ART))),
136               mFdp->ConsumeRandomLengthString(kMaxLen)));
137       list.push_back(tempList);
138     }
139     folder_cb.Run(list);
140   }
141   using GetAddressedPlayerCallback = base::Callback<void(uint16_t)>;
GetAddressedPlayer(GetAddressedPlayerCallback addressed_player)142   void GetAddressedPlayer(GetAddressedPlayerCallback addressed_player) {
143     uint16_t currentPlayer = mFdp->ConsumeIntegral<uint16_t>();
144     addressed_player.Run(currentPlayer);
145   }
146   using SetBrowsedPlayerCallback =
147           base::Callback<void(bool success, std::string root_id, uint32_t num_items)>;
SetBrowsedPlayer(uint16_t player_id,SetBrowsedPlayerCallback browse_cb)148   void SetBrowsedPlayer(uint16_t player_id, SetBrowsedPlayerCallback browse_cb) {
149     std::string rootId = mFdp->ConsumeRandomLengthString(kMaxLen);
150     uint32_t numItems = mFdp->ConsumeIntegral<uint32_t>();
151     browse_cb.Run(player_id, rootId, numItems);
152     return;
153   }
154   using SetAddressedPlayerCallback = base::Callback<void(uint16_t)>;
SetAddressedPlayer(uint16_t player_id,SetAddressedPlayerCallback new_player)155   void SetAddressedPlayer(uint16_t player_id, SetAddressedPlayerCallback new_player) {
156     new_player.Run(player_id);
157   }
PlayItem(uint16_t,bool,std::string)158   void PlayItem(uint16_t /* player_id */, bool /* now_playing */, std::string /* media_id */) {
159     return;
160   }
SetActiveDevice(const RawAddress &)161   void SetActiveDevice(const RawAddress& /* address */) { return; }
RegisterUpdateCallback(MediaCallbacks *)162   void RegisterUpdateCallback(MediaCallbacks* /* callback */) { return; }
UnregisterUpdateCallback(MediaCallbacks *)163   void UnregisterUpdateCallback(MediaCallbacks* /* callback */) { return; }
164 
165 private:
166   FuzzedDataProvider* mFdp;
167 };
168 
169 class FakeVolumeInterface : public VolumeInterface {
170 public:
FakeVolumeInterface(FuzzedDataProvider * fdp)171   FakeVolumeInterface(FuzzedDataProvider* fdp) : mFdp(fdp) {}
DeviceConnected(const RawAddress &)172   void DeviceConnected(const RawAddress& /* bdaddr */) { return; }
DeviceConnected(const RawAddress &,VolumeChangedCb cb)173   void DeviceConnected(const RawAddress& /* bdaddr */, VolumeChangedCb cb) {
174     uint8_t volume = mFdp->ConsumeIntegral<uint8_t>();
175     cb.Run(volume);
176     return;
177   }
DeviceDisconnected(const RawAddress &)178   void DeviceDisconnected(const RawAddress& /* bdaddr */) { return; }
SetVolume(int8_t)179   void SetVolume(int8_t /* volume */) { return; }
180 
181 private:
182   FuzzedDataProvider* mFdp;
183 };
184 
185 class FakePlayerSettingsInterface : public PlayerSettingsInterface {
186 public:
FakePlayerSettingsInterface(FuzzedDataProvider * fdp)187   FakePlayerSettingsInterface(FuzzedDataProvider* fdp) : mFdp(fdp) {}
ListPlayerSettings(ListPlayerSettingsCallback cb)188   void ListPlayerSettings(ListPlayerSettingsCallback cb) {
189     uint8_t label = mFdp->ConsumeIntegral<uint8_t>();
190     size_t size = mFdp->ConsumeIntegralInRange<uint8_t>(kMinSize, kMaxSize);
191     std::vector<PlayerAttribute> attributes;
192     for (size_t iter = 0; iter < size; ++iter) {
193       PlayerAttribute playerAttr = (PlayerAttribute)mFdp->ConsumeIntegralInRange<uint8_t>(
194               uint8_t(PlayerAttribute::EQUALIZER), uint8_t(PlayerAttribute::SCAN));
195       attributes.push_back(playerAttr);
196     }
197     cb.Run(attributes);
198     return;
199   }
ListPlayerSettingValues(PlayerAttribute setting,ListPlayerSettingValuesCallback cb)200   void ListPlayerSettingValues(PlayerAttribute setting, ListPlayerSettingValuesCallback cb) {
201     size_t size = mFdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
202     std::vector<uint8_t> values = mFdp->ConsumeBytes<uint8_t>(size);
203     cb.Run(setting, values);
204     return;
205   }
GetCurrentPlayerSettingValue(std::vector<PlayerAttribute> attributes,GetCurrentPlayerSettingValueCallback cb)206   void GetCurrentPlayerSettingValue(std::vector<PlayerAttribute> attributes,
207                                     GetCurrentPlayerSettingValueCallback cb) {
208     std::vector<uint8_t> values(attributes.size());
209     for (size_t iter = 0; iter < attributes.size(); ++iter) {
210       values.push_back(mFdp->ConsumeIntegral<uint8_t>());
211     }
212     cb.Run(attributes, values);
213     return;
214   }
SetPlayerSettings(std::vector<PlayerAttribute>,std::vector<uint8_t>,SetPlayerSettingValueCallback cb)215   void SetPlayerSettings(std::vector<PlayerAttribute> /* attributes */,
216                          std::vector<uint8_t> /* values */, SetPlayerSettingValueCallback cb) {
217     bool success = mFdp->ConsumeBool();
218     cb.Run(success);
219     return;
220   }
221 
222 private:
223   FuzzedDataProvider* mFdp;
224 };
225 
226 class FakeA2dpInterface : public A2dpInterface {
227 public:
active_peer()228   RawAddress active_peer() { return RawAddress::kAny; }
is_peer_in_silence_mode(const RawAddress &)229   bool is_peer_in_silence_mode(const RawAddress& /* peer_address */) { return false; }
connect_audio_sink_delayed(uint8_t,const RawAddress &)230   void connect_audio_sink_delayed(uint8_t /* handle */, const RawAddress& /* peer_address */) {
231     return;
232   }
find_audio_sink_service(const RawAddress &,tA2DP_FIND_CBACK)233   uint16_t find_audio_sink_service(const RawAddress& /* peer_address */,
234                                    tA2DP_FIND_CBACK /* p_cback */) override {
235     return 0;
236   }
237 };
238 
get_pts_avrcp_test(void)239 bool get_pts_avrcp_test(void) { return false; }
240 
241 const stack_config_t interface = {get_pts_avrcp_test,
242                                   nullptr,
243                                   nullptr,
244                                   nullptr,
245                                   nullptr,
246                                   nullptr,
247                                   nullptr,
248                                   nullptr,
249                                   nullptr,
250                                   nullptr,
251                                   nullptr,
252                                   nullptr,
253                                   nullptr,
254                                   nullptr,
255                                   nullptr,
256                                   nullptr,
257                                   nullptr,
258                                   nullptr,
259                                   nullptr,
260                                   nullptr,
261                                   nullptr,
262                                   nullptr};
263 
Callback(uint8_t,bool,std::unique_ptr<::bluetooth::PacketBuilder>)264 void Callback(uint8_t, bool, std::unique_ptr<::bluetooth::PacketBuilder>) {}
265 
266 class AVRCPDeviceFuzzer {
267 public:
AVRCPDeviceFuzzer(const uint8_t * Data,size_t Size)268   AVRCPDeviceFuzzer(const uint8_t* Data, size_t Size) : mFdp(Data, Size) {}
269   void Process();
270 
271 private:
272   void CreateBrowsePacket(std::vector<uint8_t>& packet);
273   void CreateAvrcpPacket(std::vector<uint8_t>& packet);
274   FuzzedDataProvider mFdp;
275 };
276 
CreateBrowsePacket(std::vector<uint8_t> & packet)277 void AVRCPDeviceFuzzer::CreateBrowsePacket(std::vector<uint8_t>& packet) {
278   // Used to consume a maximum of 50% of the data to create packet.
279   // This ensures that we don't completely exhaust data and use the rest 50% for
280   // fuzzing of APIs.
281   packet = mFdp.ConsumeBytes<uint8_t>(
282           mFdp.ConsumeIntegralInRange<size_t>(0, mFdp.remaining_bytes() * 50 / 100));
283 
284   if (packet.size() < Packet::kMinSize()) {
285     packet.resize(Packet::kMinSize());
286   }
287   packet[0] = (uint8_t)mFdp.PickValueInArray(kPduVal);
288   // Set packet[1] and packet[2] to corresponding value of little endian
289   uint16_t size = packet.size() - BrowsePacket::kMinSize();
290   packet[1] = (size >> k8BitShift) & kMask;
291   packet[2] = size & kMask;
292 }
293 
CreateAvrcpPacket(std::vector<uint8_t> & packet)294 void AVRCPDeviceFuzzer::CreateAvrcpPacket(std::vector<uint8_t>& packet) {
295   // Used to consume a maximum of 50% of the data to create packet.
296   // This ensures that we don't completely exhaust data and use the rest 50% for
297   // fuzzing of APIs.
298   packet = mFdp.ConsumeBytes<uint8_t>(
299           mFdp.ConsumeIntegralInRange<size_t>(0, mFdp.remaining_bytes() * 50 / 100));
300   if (packet.size() < Packet::kMinSize()) {
301     packet.resize(Packet::kMinSize());
302   }
303   packet[0] = (uint8_t)mFdp.PickValueInArray(kValidCTypes);
304   packet[2] = (uint8_t)mFdp.PickValueInArray(kValidOpCodes);
305   if (packet[2] == uint8_t(Opcode::PASS_THROUGH)) {
306     packet.resize(PassThroughPacket::kMinSize());
307     packet[3] = mFdp.ConsumeBool() ? kMediaOpId : mFdp.ConsumeIntegral<uint8_t>();
308   } else if (packet[2] == uint8_t(Opcode::VENDOR)) {
309     if (packet.size() <= VendorPacket::kMinSize()) {
310       packet.resize(VendorPacket::kMinSize() + 1);
311     }
312     packet[3] = mFdp.ConsumeIntegralInRange<uint8_t>(kMinScope, kMaxScope);
313     packet[5] = (uint8_t)mFdp.ConsumeBool();  // Direction
314     packet[6] = (uint8_t)mFdp.PickValueInArray(kCommandPduVal);
315     // Set packet[8] and packet[9] to corresponding value of little endian
316     uint16_t size = packet.size() - VendorPacket::kMinSize();
317     packet[8] = (size >> k8BitShift) & kMask;
318     packet[9] = size & kMask;
319   }
320 }
Process()321 void AVRCPDeviceFuzzer::Process() {
322   FakeMediaInterface fmi(&mFdp);
323   FakeVolumeInterface fvi(&mFdp);
324   FakeA2dpInterface fai;
325   FakePlayerSettingsInterface fpsi(&mFdp);
326 
327   Device device(RawAddress::kAny /* bdaddr */, mFdp.ConsumeBool() /* avrcp13_compatibility */,
328                 base::BindRepeating([](uint8_t, bool, std::unique_ptr<::bluetooth::PacketBuilder>) {
329                 }) /* send_msg_cb */,
330                 mFdp.ConsumeIntegral<uint16_t>() /* ctrl_mtu */,
331                 mFdp.ConsumeIntegral<uint16_t>() /* browse_mtu */);
332 
333   device.RegisterInterfaces(&fmi, &fai, &fvi, &fpsi);
334 
335   while (mFdp.remaining_bytes()) {
336     auto invokeAVRCP = mFdp.PickValueInArray<const std::function<void()>>({
337             [&]() { device.SetBrowseMtu(mFdp.ConsumeIntegral<uint16_t>() /*  browse_mtu */); },
338             [&]() { device.SetBipClientStatus(mFdp.ConsumeBool() /* connected */); },
339             [&]() {
340               std::vector<uint8_t> browse_packet;
341               CreateBrowsePacket(browse_packet);
342               auto browse_request = TestPacketType<BrowsePacket>::Make(browse_packet);
343               device.BrowseMessageReceived(mFdp.ConsumeIntegral<uint8_t>() /* label */,
344                                            browse_request);
345             },
346             [&]() {
347               /* Crafting PassThroughPacket Packets */
348               std::vector<uint8_t> avrcp_packet;
349               CreateAvrcpPacket(avrcp_packet);
350               auto avrcp_request = TestPacketType<avrcp::Packet>::Make(avrcp_packet);
351               device.MessageReceived(mFdp.ConsumeIntegral<uint8_t>() /* label */, avrcp_request);
352             },
353             [&]() {
354               device.SendMediaUpdate(mFdp.ConsumeBool() /* metadata */,
355                                      mFdp.ConsumeBool() /* play_status */,
356                                      mFdp.ConsumeBool() /* queue */);
357             },
358             [&]() {
359               device.SendFolderUpdate(mFdp.ConsumeBool() /* available_players */,
360                                       mFdp.ConsumeBool() /* addressed_player */,
361                                       mFdp.ConsumeBool() /* uids */);
362             },
363     });
364     invokeAVRCP();
365   }
366   device.DeviceDisconnected();
367 }
368 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)369 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
370   AVRCPDeviceFuzzer avrcp_device_fuzzer(Data, Size);
371   avrcp_device_fuzzer.Process();
372   return 0;
373 }
374 }  // namespace avrcp
375 }  // namespace bluetooth
376 
stack_config_get_interface(void)377 const stack_config_t* stack_config_get_interface(void) { return &bluetooth::avrcp::interface; }
378