/src/adhd/cras/fuzz/cras_fl_media_fuzzer.cc
Line | Count | Source |
1 | | /* Copyright 2022 The ChromiumOS Authors |
2 | | * Use of this source code is governed by a BSD-style license that can be |
3 | | * found in the LICENSE file. |
4 | | */ |
5 | | #include <cstdio> |
6 | | #include <cstring> |
7 | | #include <fuzzer/FuzzedDataProvider.h> |
8 | | #include <stddef.h> |
9 | | #include <stdint.h> |
10 | | #include <stdio.h> |
11 | | #include <string.h> |
12 | | |
13 | | #include "cras/common/check.h" |
14 | | #include "cras/src/server/cras_a2dp_manager.h" |
15 | | #include "cras/src/server/cras_alert.h" |
16 | | #include "cras/src/server/cras_bt_log.h" |
17 | | #include "cras/src/server/cras_dsp.h" |
18 | | #include "cras/src/server/cras_fl_media.h" |
19 | | #include "cras/src/server/cras_fl_media_adapter.h" |
20 | | #include "cras/src/server/cras_iodev_list.h" |
21 | | #include "cras/src/server/cras_mix.h" |
22 | | #include "cras/src/server/cras_observer.h" |
23 | | #include "cras/src/server/cras_rclient.h" |
24 | | #include "cras/src/server/cras_stream_apm.h" |
25 | | #include "cras/src/server/cras_system_state.h" |
26 | | #include "cras_shm.h" |
27 | | |
28 | | #define BT_OBJECT_BASE "/org/chromium/bluetooth/hci" |
29 | | #define BT_OBJECT_MEDIA "/media" |
30 | | |
31 | | static struct fl_media* active_fm = NULL; |
32 | | static std::string addr = ""; |
33 | | static cras_rclient* client = NULL; |
34 | | |
35 | | /* This fuzzer consumes bytes of size ranging from 270 to 340. |
36 | | * Minimum fuzzing size if therefore set at 350. |
37 | | */ |
38 | | const int kMinFuzzDataSize = 350; |
39 | | const int kMaxStringLength = 100; |
40 | | |
41 | | /* rclient_buffer_on_client consumes an int and a cras_server_message |
42 | | * struct cras_connect_message is of size 99 |
43 | | */ |
44 | | const int kMinRclientMsgSize = 104; |
45 | | |
46 | | struct cras_fl_a2dp_codec_config* codecs_create( |
47 | 2.67k | FuzzedDataProvider* data_provider) { |
48 | 2.67k | int bps = data_provider->ConsumeIntegral<int>(); |
49 | 2.67k | int channels = data_provider->ConsumeIntegral<int>(); |
50 | 2.67k | int priority = data_provider->ConsumeIntegral<int>(); |
51 | 2.67k | int type = data_provider->ConsumeIntegral<int>(); |
52 | 2.67k | int rate = data_provider->ConsumeIntegral<int>(); |
53 | | |
54 | 2.67k | return cras_floss_a2dp_codec_create(bps, channels, priority, type, rate); |
55 | 2.67k | } |
56 | | |
57 | 1.33k | void active_fm_create(FuzzedDataProvider* data_provider) { |
58 | 1.33k | int hci = data_provider->ConsumeIntegral<int>(); |
59 | 1.33k | fl_media_init(hci); |
60 | 1.33k | active_fm = floss_media_get_active_fm(); |
61 | 1.33k | } |
62 | | |
63 | 2.06k | std::string get_valid_addr(FuzzedDataProvider* data_provider) { |
64 | 2.06k | const int STR_LEN = 17; |
65 | 2.06k | char str[STR_LEN + 1] = {}; |
66 | 37.0k | for (int i = 0; i < STR_LEN; i++) { |
67 | 35.0k | if ((i + 1) % 3 == 0) { |
68 | 10.3k | str[i] = ':'; |
69 | 24.7k | } else { |
70 | 24.7k | snprintf(str + i, 2, "%X", |
71 | 24.7k | data_provider->ConsumeIntegralInRange<int>(0, 15)); |
72 | 24.7k | } |
73 | 35.0k | } |
74 | 2.06k | return std::string(str); |
75 | 2.06k | } |
76 | | |
77 | 612 | std::string get_random_addr(FuzzedDataProvider* data_provider) { |
78 | 612 | return data_provider->ConsumeRandomLengthString(kMaxStringLength); |
79 | 612 | } |
80 | | |
81 | 2.67k | void fuzzer_on_bluetooth_device_added(FuzzedDataProvider* data_provider) { |
82 | 2.67k | struct cras_fl_a2dp_codec_config* codecs = codecs_create(data_provider); |
83 | | |
84 | 2.67k | int32_t hfp_cap = data_provider->ConsumeIntegral<int32_t>(); |
85 | 2.67k | bool abs_vol_supported = data_provider->ConsumeBool(); |
86 | | |
87 | 2.67k | if (data_provider->ConsumeBool()) { |
88 | 2.06k | addr = get_valid_addr(data_provider); |
89 | 2.06k | } else { |
90 | 612 | addr = get_random_addr(data_provider); |
91 | 612 | } |
92 | 2.67k | std::string name = data_provider->ConsumeRandomLengthString(kMaxStringLength); |
93 | | |
94 | 2.67k | handle_on_bluetooth_device_added(active_fm, addr.c_str(), name.c_str(), |
95 | 2.67k | codecs, hfp_cap, abs_vol_supported); |
96 | 2.67k | free(codecs); |
97 | 2.67k | codecs = NULL; |
98 | 2.67k | } |
99 | | |
100 | 1.33k | void fuzzer_on_bluetooth_device_removed() { |
101 | 1.33k | handle_on_bluetooth_device_removed(active_fm, addr.c_str()); |
102 | 1.33k | } |
103 | | |
104 | | void fuzzer_on_absolute_volume_supported_changed( |
105 | 1.33k | FuzzedDataProvider* data_provider) { |
106 | 1.33k | bool abs_vol_supported = data_provider->ConsumeBool(); |
107 | 1.33k | handle_on_absolute_volume_supported_changed(active_fm, abs_vol_supported); |
108 | 1.33k | } |
109 | | |
110 | 1.33k | void fuzzer_on_absolute_volume_changed(FuzzedDataProvider* data_provider) { |
111 | 1.33k | uint8_t volume = data_provider->ConsumeIntegral<uint8_t>(); |
112 | 1.33k | handle_on_absolute_volume_changed(active_fm, volume); |
113 | 1.33k | } |
114 | | |
115 | 2.67k | void fuzzer_on_hfp_volume_changed(FuzzedDataProvider* data_provider) { |
116 | 2.67k | uint8_t volume = data_provider->ConsumeIntegral<uint8_t>(); |
117 | 2.67k | handle_on_hfp_volume_changed(active_fm, addr.c_str(), volume); |
118 | 2.67k | } |
119 | | |
120 | 0 | void fuzzer_on_hfp_audio_disconnected(FuzzedDataProvider* data_provider) { |
121 | 0 | handle_on_hfp_audio_disconnected(active_fm, addr.c_str()); |
122 | 0 | } |
123 | | |
124 | 1.33k | void fuzzer_rclient_buffer_on_client(FuzzedDataProvider* data_provider) { |
125 | 1.33k | if (data_provider->remaining_bytes() < kMinRclientMsgSize) { |
126 | 147 | return; |
127 | 147 | } |
128 | 1.18k | int fds[1] = {0}; |
129 | 1.18k | int num_fds = data_provider->ConsumeIntegralInRange(0, 1); |
130 | 1.18k | std::vector<uint8_t> msg_byte = |
131 | 1.18k | data_provider->ConsumeBytes<uint8_t>(sizeof(struct cras_connect_message)); |
132 | 1.18k | struct cras_server_message* msg = |
133 | 1.18k | (struct cras_server_message*)msg_byte.data(); |
134 | 1.18k | msg->length = msg_byte.size(); |
135 | 1.18k | cras_rclient_buffer_from_client(client, (const uint8_t*)msg, msg->length, fds, |
136 | 1.18k | num_fds); |
137 | 1.18k | } |
138 | | |
139 | 5.94k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
140 | 5.94k | client = cras_rclient_create(0, 0, CRAS_CONTROL); |
141 | 5.94k | if (size < kMinFuzzDataSize) { |
142 | 3.76k | handle_on_bluetooth_device_added(NULL, NULL, NULL, NULL, 0, 0); |
143 | 3.76k | cras_rclient_buffer_from_client(client, data, size, NULL, 0); |
144 | 3.76k | } else { |
145 | 2.18k | FuzzedDataProvider data_provider(data, size); |
146 | 2.18k | active_fm_create(&data_provider); |
147 | 2.18k | fuzzer_on_bluetooth_device_added(&data_provider); |
148 | 2.18k | fuzzer_on_bluetooth_device_added(&data_provider); |
149 | 2.18k | fuzzer_on_absolute_volume_supported_changed(&data_provider); |
150 | 2.18k | fuzzer_on_absolute_volume_changed(&data_provider); |
151 | 2.18k | fuzzer_on_hfp_volume_changed(&data_provider); |
152 | 2.18k | fuzzer_rclient_buffer_on_client(&data_provider); |
153 | 2.18k | fuzzer_on_bluetooth_device_removed(); |
154 | 2.18k | fuzzer_on_hfp_volume_changed(&data_provider); |
155 | 2.18k | cras_alert_process_all_pending_alerts(); |
156 | 2.18k | fl_media_destroy(&active_fm); |
157 | 2.18k | } |
158 | 5.94k | cras_rclient_destroy(client); |
159 | 5.94k | return 0; |
160 | 5.94k | } |
161 | | |
162 | 2 | extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { |
163 | 2 | char* shm_name; |
164 | 2 | if (asprintf(&shm_name, "/cras-%d", getpid()) < 0) { |
165 | 0 | exit(-ENOMEM); |
166 | 0 | } |
167 | 2 | struct cras_server_state* exp_state = |
168 | 2 | (struct cras_server_state*)calloc(1, sizeof(*exp_state)); |
169 | | |
170 | 2 | int rw_shm_fd = open("/dev/null", O_RDWR); |
171 | 2 | int ro_shm_fd = open("/dev/null", O_RDONLY); |
172 | | |
173 | 2 | cras_system_state_init("/tmp", shm_name, rw_shm_fd, ro_shm_fd, exp_state, |
174 | 2 | sizeof(*exp_state)); |
175 | 2 | free(shm_name); |
176 | | |
177 | 2 | cras_observer_server_init(); |
178 | 2 | btlog = cras_bt_event_log_init(); |
179 | | |
180 | 2 | cras_mix_init(); |
181 | 2 | cras_stream_apm_init("/etc/cras"); |
182 | 2 | cras_iodev_list_init(); |
183 | | /* For cros fuzz, emerge adhd with USE=fuzzer will copy dsp.ini.sample to |
184 | | * etc/cras. For OSS-Fuzz the Dockerfile will be responsible for copying the |
185 | | * file. This shouldn't crash CRAS even if the dsp file does not exist. */ |
186 | 2 | cras_dsp_init("/etc/cras/dsp.ini.sample"); |
187 | 2 | return 0; |
188 | 2 | } |