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((void**)&result.get_items.p_item_list[i].u.player.name.p_str);
106 break;
107 case AVRC_ITEM_FOLDER:
108 osi_free_and_reset((void**)&result.get_items.p_item_list[i].u.folder.name.p_str);
109 break;
110 case AVRC_ITEM_MEDIA:
111 osi_free_and_reset((void**)&result.get_items.p_item_list[i].u.media.name.p_str);
112 for (int j = 0; j < result.get_items.p_item_list[i].u.media.attr_count; j++) {
113 osi_free_and_reset(
114 (void**)&result.get_items.p_item_list[i].u.media.p_attr_list[j].name.p_str);
115 }
116 osi_free_and_reset((void**)&result.get_items.p_item_list[i].u.media.p_attr_list);
117 break;
118 }
119 }
120 osi_free_and_reset((void**)&result.get_items.p_item_list);
121 break;
122
123 case AVRC_PDU_CHANGE_PATH:
124 break;
125
126 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
127 for (int i = 0; i < result.get_attrs.num_attrs; i++) {
128 osi_free_and_reset((void**)&result.get_attrs.p_attrs[i].name.p_str);
129 }
130 osi_free_and_reset((void**)&result.get_attrs.p_attrs);
131 break;
132
133 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
134 break;
135
136 case AVRC_PDU_SEARCH:
137 break;
138 }
139 }
140
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)141 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
142 uint8_t scratch_buf[512]{};
143 uint16_t scratch_buf_len = 512;
144 tAVRC_MSG msg{};
145 tAVRC_RESPONSE result{};
146
147 if (size < 2) {
148 return 0;
149 }
150
151 /* 4 command type codes
152 * AVRC_CMD_CTRL 0
153 * AVRC_CMD_STATUS 1
154 * AVRC_CMD_SPEC_INQ 2
155 * AVRC_CMD_NOTIF 3
156 */
157 msg.hdr.ctype = data[0] % 4;
158
159 /* AVRC_Ctrl_ParsResponse handles opcode with AVRC_OP_VENDOR and
160 * AVRC_OP_BROWSE
161 * AVRC_ParsResponse handles opcode with AVRC_OP_VENDOR and
162 * AVRC_OP_PASS_THRU
163 * So we got 3 cases here */
164 switch (data[1] % 3) {
165 case 0:
166 msg.hdr.opcode = AVRC_OP_PASS_THRU;
167 msg.pass.p_pass_data = (uint8_t*)&data[2];
168 msg.pass.pass_len = size - 2;
169 break;
170 case 1:
171 msg.hdr.opcode = AVRC_OP_VENDOR;
172 msg.vendor.p_vendor_data = (uint8_t*)&data[2];
173 msg.vendor.vendor_len = size - 2;
174 break;
175 case 2:
176 msg.hdr.opcode = AVRC_OP_BROWSE;
177 msg.browse.p_browse_data = (uint8_t*)&data[2];
178 msg.browse.browse_len = size - 2;
179 break;
180 }
181
182 AVRC_Ctrl_ParsResponse(&msg, &result, scratch_buf, &scratch_buf_len);
183 free_avrc_response(result);
184
185 memset(&result, 0, sizeof(result));
186 AVRC_ParsResponse(&msg, &result, scratch_buf, scratch_buf_len);
187 free_avrc_response(result);
188
189 return 0;
190 }
191