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