1 /*
2  * Copyright 2022 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 #include "osi/include/allocator.h"
18 #include "stack/include/avrc_api.h"
19 
free_avrc_response(tAVRC_RESPONSE & result)20 static void free_avrc_response(tAVRC_RESPONSE& result) {
21   // AVRC_BldResponse
22   switch (result.pdu) {
23     case AVRC_PDU_NEXT_GROUP:
24     case AVRC_PDU_PREV_GROUP:
25       break;
26 
27     case AVRC_PDU_GET_CAPABILITIES:
28       break;
29 
30     case AVRC_PDU_LIST_PLAYER_APP_ATTR:
31       break;
32 
33     case AVRC_PDU_LIST_PLAYER_APP_VALUES:
34       break;
35 
36     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
37       osi_free_and_reset((void**)&result.get_cur_app_val.p_vals);
38       break;
39 
40     case AVRC_PDU_SET_PLAYER_APP_VALUE:
41       break;
42 
43     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
44       for (int i = 0; i < result.get_app_attr_txt.num_attr; i++) {
45         osi_free_and_reset((void**)&result.get_app_attr_txt.p_attrs[i].p_str);
46       }
47       osi_free_and_reset((void**)&result.get_app_attr_txt.p_attrs);
48       break;
49 
50     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
51       for (int i = 0; i < result.get_app_val_txt.num_attr; i++) {
52         osi_free_and_reset((void**)&result.get_app_val_txt.p_attrs[i].p_str);
53       }
54       osi_free_and_reset((void**)&result.get_app_val_txt.p_attrs);
55       break;
56 
57     case AVRC_PDU_INFORM_DISPLAY_CHARSET:
58       break;
59 
60     case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
61       break;
62 
63     case AVRC_PDU_GET_ELEMENT_ATTR:
64       for (int i = 0; i < result.get_attrs.num_attrs; i++) {
65         osi_free_and_reset((void**)&result.get_attrs.p_attrs[i].name.p_str);
66       }
67       osi_free_and_reset((void**)&result.get_attrs.p_attrs);
68       break;
69 
70     case AVRC_PDU_GET_PLAY_STATUS:
71       break;
72 
73     case AVRC_PDU_REGISTER_NOTIFICATION:
74       break;
75 
76     case AVRC_PDU_REQUEST_CONTINUATION_RSP:
77       break;
78 
79     case AVRC_PDU_ABORT_CONTINUATION_RSP:
80       break;
81 
82     case AVRC_PDU_SET_ADDRESSED_PLAYER:
83       break;
84 
85     case AVRC_PDU_PLAY_ITEM:
86       break;
87 
88     case AVRC_PDU_SET_ABSOLUTE_VOLUME:
89       break;
90 
91     case AVRC_PDU_ADD_TO_NOW_PLAYING:
92       break;
93 
94     case AVRC_PDU_SET_BROWSED_PLAYER:
95       for (int i = 0; i < result.br_player.folder_depth; i++) {
96         osi_free_and_reset((void**)&result.br_player.p_folders[i].p_str);
97       }
98       osi_free_and_reset((void**)&result.br_player.p_folders);
99       break;
100 
101     case AVRC_PDU_GET_FOLDER_ITEMS:
102       for (int i = 0; i < result.get_items.item_count; i++) {
103         switch (result.get_items.p_item_list[i].item_type) {
104           case AVRC_ITEM_PLAYER:
105             osi_free_and_reset(
106                 (void**)&result.get_items.p_item_list[i].u.player.name.p_str);
107             break;
108           case AVRC_ITEM_FOLDER:
109             osi_free_and_reset(
110                 (void**)&result.get_items.p_item_list[i].u.folder.name.p_str);
111             break;
112           case AVRC_ITEM_MEDIA:
113             osi_free_and_reset(
114                 (void**)&result.get_items.p_item_list[i].u.media.name.p_str);
115             for (int j = 0;
116                  j < result.get_items.p_item_list[i].u.media.attr_count; j++) {
117               osi_free_and_reset((void**)&result.get_items.p_item_list[i]
118                                      .u.media.p_attr_list[j]
119                                      .name.p_str);
120             }
121             osi_free_and_reset(
122                 (void**)&result.get_items.p_item_list[i].u.media.p_attr_list);
123             break;
124         }
125       }
126       osi_free_and_reset((void**)&result.get_items.p_item_list);
127       break;
128 
129     case AVRC_PDU_CHANGE_PATH:
130       break;
131 
132     case AVRC_PDU_GET_ITEM_ATTRIBUTES:
133       for (int i = 0; i < result.get_attrs.num_attrs; i++) {
134         osi_free_and_reset((void**)&result.get_attrs.p_attrs[i].name.p_str);
135       }
136       osi_free_and_reset((void**)&result.get_attrs.p_attrs);
137       break;
138 
139     case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
140       break;
141 
142     case AVRC_PDU_SEARCH:
143       break;
144   }
145 }
146 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)147 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
148   uint8_t scratch_buf[512]{};
149   uint16_t scratch_buf_len = 512;
150   tAVRC_MSG msg{};
151   tAVRC_RESPONSE result{};
152 
153   if (size < 2) return 0;
154 
155   /* 4 command type codes
156    * AVRC_CMD_CTRL 0
157    * AVRC_CMD_STATUS 1
158    * AVRC_CMD_SPEC_INQ 2
159    * AVRC_CMD_NOTIF 3
160    */
161   msg.hdr.ctype = data[0] % 4;
162 
163   /* AVRC_Ctrl_ParsResponse handles opcode with AVRC_OP_VENDOR and
164    * AVRC_OP_BROWSE
165    * AVRC_ParsResponse handles opcode with AVRC_OP_VENDOR and
166    * AVRC_OP_PASS_THRU
167    * So we got 3 cases here */
168   switch (data[1] % 3) {
169     case 0:
170       msg.hdr.opcode = AVRC_OP_PASS_THRU;
171       msg.pass.p_pass_data = (uint8_t*)&data[2];
172       msg.pass.pass_len = size - 2;
173       break;
174     case 1:
175       msg.hdr.opcode = AVRC_OP_VENDOR;
176       msg.vendor.p_vendor_data = (uint8_t*)&data[2];
177       msg.vendor.vendor_len = size - 2;
178       break;
179     case 2:
180       msg.hdr.opcode = AVRC_OP_BROWSE;
181       msg.browse.p_browse_data = (uint8_t*)&data[2];
182       msg.browse.browse_len = size - 2;
183       break;
184   }
185 
186   AVRC_Ctrl_ParsResponse(&msg, &result, scratch_buf, &scratch_buf_len);
187   free_avrc_response(result);
188 
189   memset(&result, 0, sizeof(result));
190   AVRC_ParsResponse(&msg, &result, scratch_buf, scratch_buf_len);
191   free_avrc_response(result);
192 
193   return 0;
194 }
195