1 /*
2 * Copyright (C) 2021 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 "aaudio/AAudio.h"
19 #include "aaudio/AAudioTesting.h"
20 #include <fuzzer/FuzzedDataProvider.h>
21
22 #include <functional>
23
24 constexpr int32_t kRandomStringLength = 256;
25 constexpr int32_t kMaxRuns = 100;
26 constexpr int64_t kNanosPerMillisecond = 1000 * 1000;
27
28 constexpr aaudio_direction_t kDirections[] = {
29 AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT, AAUDIO_UNSPECIFIED};
30
31 constexpr aaudio_performance_mode_t kPerformanceModes[] = {
32 AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
33 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_UNSPECIFIED};
34
35 constexpr aaudio_format_t kFormats[] = {
36 AAUDIO_FORMAT_INVALID, AAUDIO_FORMAT_UNSPECIFIED,
37 AAUDIO_FORMAT_PCM_I16, AAUDIO_FORMAT_PCM_FLOAT,
38 AAUDIO_FORMAT_PCM_I24_PACKED, AAUDIO_FORMAT_PCM_I32};
39
40 constexpr aaudio_sharing_mode_t kSharingModes[] = {
41 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_SHARING_MODE_SHARED};
42
43 constexpr int32_t kSampleRates[] = {AAUDIO_UNSPECIFIED,
44 8000,
45 11025,
46 16000,
47 22050,
48 32000,
49 44100,
50 48000,
51 88200,
52 96000};
53
54 constexpr aaudio_usage_t kUsages[] = {
55 AAUDIO_USAGE_MEDIA,
56 AAUDIO_USAGE_VOICE_COMMUNICATION,
57 AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
58 AAUDIO_USAGE_ALARM,
59 AAUDIO_USAGE_NOTIFICATION,
60 AAUDIO_USAGE_NOTIFICATION_RINGTONE,
61 AAUDIO_USAGE_NOTIFICATION_EVENT,
62 AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
63 AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
64 AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
65 AAUDIO_USAGE_GAME,
66 AAUDIO_USAGE_ASSISTANT,
67 AAUDIO_SYSTEM_USAGE_EMERGENCY,
68 AAUDIO_SYSTEM_USAGE_SAFETY,
69 AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
70 AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT,
71 AAUDIO_UNSPECIFIED};
72
73 constexpr aaudio_content_type_t kContentTypes[] = {
74 AAUDIO_CONTENT_TYPE_SPEECH, AAUDIO_CONTENT_TYPE_MUSIC,
75 AAUDIO_CONTENT_TYPE_MOVIE, AAUDIO_CONTENT_TYPE_SONIFICATION,
76 AAUDIO_UNSPECIFIED};
77
78 constexpr aaudio_input_preset_t kInputPresets[] = {
79 AAUDIO_INPUT_PRESET_GENERIC,
80 AAUDIO_INPUT_PRESET_CAMCORDER,
81 AAUDIO_INPUT_PRESET_VOICE_RECOGNITION,
82 AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
83 AAUDIO_INPUT_PRESET_UNPROCESSED,
84 AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
85 AAUDIO_UNSPECIFIED};
86
87 constexpr aaudio_allowed_capture_policy_t kAllowedCapturePolicies[] = {
88 AAUDIO_ALLOW_CAPTURE_BY_ALL, AAUDIO_ALLOW_CAPTURE_BY_SYSTEM,
89 AAUDIO_ALLOW_CAPTURE_BY_NONE, AAUDIO_UNSPECIFIED};
90
91 constexpr aaudio_session_id_t kSessionIds[] = {
92 AAUDIO_SESSION_ID_NONE, AAUDIO_SESSION_ID_ALLOCATE, AAUDIO_UNSPECIFIED};
93
94 constexpr aaudio_policy_t kPolicies[] = {
95 AAUDIO_POLICY_NEVER, AAUDIO_POLICY_AUTO, AAUDIO_POLICY_ALWAYS,
96 AAUDIO_UNSPECIFIED};
97
98 class LibAaudioFuzzer {
99 public:
~LibAaudioFuzzer()100 ~LibAaudioFuzzer() { deInit(); }
101 bool init();
102 void invokeAAudioSetAPIs(FuzzedDataProvider &fdp);
103 void process(const uint8_t *data, size_t size);
104 void deInit();
105
106 private:
107 AAudioStreamBuilder *mAaudioBuilder = nullptr;
108 AAudioStream *mAaudioStream = nullptr;
109 };
110
init()111 bool LibAaudioFuzzer::init() {
112 aaudio_result_t result = AAudio_createStreamBuilder(&mAaudioBuilder);
113 if ((result != AAUDIO_OK) || (!mAaudioBuilder)) {
114 return false;
115 }
116 return true;
117 }
118
invokeAAudioSetAPIs(FuzzedDataProvider & fdp)119 void LibAaudioFuzzer::invokeAAudioSetAPIs(FuzzedDataProvider &fdp){
120 aaudio_performance_mode_t mode = fdp.PickValueInArray(
121 {fdp.PickValueInArray(kPerformanceModes), fdp.ConsumeIntegral<int32_t>()});
122 AAudioStreamBuilder_setPerformanceMode(mAaudioBuilder, mode);
123
124 int32_t deviceId = fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
125 AAudioStreamBuilder_setDeviceId(mAaudioBuilder, deviceId);
126
127 std::string packageName =
128 fdp.PickValueInArray<std::string>({"android.nativemedia.aaudio", "android.app.appops.cts",
129 fdp.ConsumeRandomLengthString(kRandomStringLength)});
130 AAudioStreamBuilder_setPackageName(mAaudioBuilder, packageName.c_str());
131
132 std::string attributionTag = fdp.ConsumeRandomLengthString(kRandomStringLength);
133 AAudioStreamBuilder_setAttributionTag(mAaudioBuilder, attributionTag.c_str());
134
135 int32_t sampleRate = fdp.PickValueInArray(kSampleRates);
136 AAudioStreamBuilder_setSampleRate(mAaudioBuilder, sampleRate);
137
138 int32_t channelCount = fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
139 AAudioStreamBuilder_setChannelCount(mAaudioBuilder, channelCount);
140
141 aaudio_direction_t direction =
142 fdp.PickValueInArray({fdp.PickValueInArray(kDirections), fdp.ConsumeIntegral<int32_t>()});
143 AAudioStreamBuilder_setDirection(mAaudioBuilder, direction);
144
145 aaudio_format_t format =
146 fdp.PickValueInArray({fdp.PickValueInArray(kFormats), fdp.ConsumeIntegral<int32_t>()});
147 AAudioStreamBuilder_setFormat(mAaudioBuilder, format);
148
149 aaudio_sharing_mode_t sharingMode = fdp.PickValueInArray(
150 {fdp.PickValueInArray(kSharingModes), fdp.ConsumeIntegral<int32_t>()});
151 AAudioStreamBuilder_setSharingMode(mAaudioBuilder, sharingMode);
152
153 aaudio_usage_t usage =
154 fdp.PickValueInArray({fdp.PickValueInArray(kUsages), fdp.ConsumeIntegral<int32_t>()});
155 AAudioStreamBuilder_setUsage(mAaudioBuilder, usage);
156
157 aaudio_content_type_t contentType = fdp.PickValueInArray(
158 {fdp.PickValueInArray(kContentTypes), fdp.ConsumeIntegral<int32_t>()});
159 AAudioStreamBuilder_setContentType(mAaudioBuilder, contentType);
160
161 aaudio_input_preset_t inputPreset = fdp.PickValueInArray(
162 {fdp.PickValueInArray(kInputPresets), fdp.ConsumeIntegral<int32_t>()});
163 AAudioStreamBuilder_setInputPreset(mAaudioBuilder, inputPreset);
164
165 bool privacySensitive = fdp.ConsumeBool();
166 AAudioStreamBuilder_setPrivacySensitive(mAaudioBuilder, privacySensitive);
167
168 int32_t frames = fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
169 AAudioStreamBuilder_setBufferCapacityInFrames(mAaudioBuilder, frames);
170
171 aaudio_allowed_capture_policy_t allowedCapturePolicy = fdp.PickValueInArray(
172 {fdp.PickValueInArray(kAllowedCapturePolicies), fdp.ConsumeIntegral<int32_t>()});
173 AAudioStreamBuilder_setAllowedCapturePolicy(mAaudioBuilder, allowedCapturePolicy);
174
175 aaudio_session_id_t sessionId =
176 fdp.PickValueInArray({fdp.PickValueInArray(kSessionIds), fdp.ConsumeIntegral<int32_t>()});
177 AAudioStreamBuilder_setSessionId(mAaudioBuilder, sessionId);
178
179 AAudioStreamBuilder_setDataCallback(mAaudioBuilder, nullptr, nullptr);
180 AAudioStreamBuilder_setErrorCallback(mAaudioBuilder, nullptr, nullptr);
181
182 int32_t framesPerDataCallback =
183 fdp.PickValueInArray({AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
184 AAudioStreamBuilder_setFramesPerDataCallback(mAaudioBuilder, framesPerDataCallback);
185
186 aaudio_policy_t policy =
187 fdp.PickValueInArray({fdp.PickValueInArray(kPolicies), fdp.ConsumeIntegral<int32_t>()});
188 AAudio_setMMapPolicy(policy);
189 }
190
process(const uint8_t * data,size_t size)191 void LibAaudioFuzzer::process(const uint8_t *data, size_t size) {
192 FuzzedDataProvider fdp(data, size);
193 int32_t maxFrames = 0;
194 int32_t count = 0;
195 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
196
197 invokeAAudioSetAPIs(fdp);
198
199 aaudio_result_t result = AAudioStreamBuilder_openStream(mAaudioBuilder, &mAaudioStream);
200 if ((result != AAUDIO_OK) || (!mAaudioStream)) {
201 return;
202 }
203 /* The 'runs' variable serves to set an upper limit on the loop iterations, preventing excessive
204 * execution.
205 */
206 int32_t runs = kMaxRuns;
207 while (fdp.remaining_bytes() > 0 && --runs) {
208 auto AAudioapi = fdp.PickValueInArray<const std::function<void()>>({
209 [&]() { (void)AAudio_getMMapPolicy(); },
210
211 [&]() {
212 int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mAaudioStream);
213 uint8_t numberOfBursts = fdp.ConsumeIntegral<uint8_t>();
214 maxFrames = numberOfBursts * framesPerBurst;
215 int32_t requestedBufferSize = fdp.ConsumeIntegral<uint16_t>() * framesPerBurst;
216 AAudioStream_setBufferSizeInFrames(mAaudioStream, requestedBufferSize);
217 },
218 [&]() {
219 int64_t position = 0, nanoseconds = 0;
220 AAudioStream_getTimestamp(mAaudioStream, CLOCK_MONOTONIC, &position, &nanoseconds);
221 },
222 [&]() {
223 AAudioStream_requestStart(mAaudioStream);
224 },
225 [&]() {
226 AAudioStream_requestPause(mAaudioStream);
227 },
228 [&]() {
229 AAudioStream_requestFlush(mAaudioStream);
230 },
231 [&]() {
232 AAudioStream_requestStop(mAaudioStream);
233 },
234 [&]() {
235 aaudio_format_t actualFormat = AAudioStream_getFormat(mAaudioStream);
236 int32_t actualChannelCount = AAudioStream_getChannelCount(mAaudioStream);
237
238 count = fdp.ConsumeIntegral<int32_t>();
239 aaudio_direction_t direction = AAudioStream_getDirection(mAaudioStream);
240
241 if (actualFormat == AAUDIO_FORMAT_PCM_I16) {
242 std::vector<int16_t> inputShortData(maxFrames * actualChannelCount, 0x0);
243 if (direction == AAUDIO_DIRECTION_INPUT) {
244 AAudioStream_read(mAaudioStream, inputShortData.data(), maxFrames,
245 count * kNanosPerMillisecond);
246 } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
247 AAudioStream_write(mAaudioStream, inputShortData.data(), maxFrames,
248 count * kNanosPerMillisecond);
249 }
250 } else if (actualFormat == AAUDIO_FORMAT_PCM_FLOAT) {
251 std::vector<float> inputFloatData(maxFrames * actualChannelCount, 0x0);
252 if (direction == AAUDIO_DIRECTION_INPUT) {
253 AAudioStream_read(mAaudioStream, inputFloatData.data(), maxFrames,
254 count * kNanosPerMillisecond);
255 } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
256 AAudioStream_write(mAaudioStream, inputFloatData.data(), maxFrames,
257 count * kNanosPerMillisecond);
258 }
259 }
260 },
261 [&]() {
262 AAudioStream_waitForStateChange(mAaudioStream, AAUDIO_STREAM_STATE_UNKNOWN, &state,
263 count * kNanosPerMillisecond);
264 },
265 [&]() { (void)AAudio_convertStreamStateToText(state); },
266 [&]() {
267 (void)AAudioStream_getState(mAaudioStream);
268 },
269 [&]() {
270 (void)AAudioStream_getUsage(mAaudioStream);
271 },
272 [&]() {
273 (void)AAudioStream_getSamplesPerFrame(mAaudioStream);
274 },
275 [&]() {
276 (void)AAudioStream_getContentType(mAaudioStream);
277 },
278 [&]() {
279 (void)AAudioStream_getInputPreset(mAaudioStream);
280 },
281 [&]() {
282 (void)AAudioStream_isPrivacySensitive(mAaudioStream);
283 },
284 [&]() {
285 (void)AAudioStream_getAllowedCapturePolicy(mAaudioStream);
286 },
287 [&]() {
288 (void)AAudioStream_getPerformanceMode(mAaudioStream);
289 },
290 [&]() {
291 (void)AAudioStream_getDeviceId(mAaudioStream);
292 },
293 [&]() {
294 (void)AAudioStream_getSharingMode(mAaudioStream);
295 },
296 [&]() {
297 (void)AAudioStream_getSessionId(mAaudioStream);
298 },
299 [&]() {
300 (void)AAudioStream_getFramesRead(mAaudioStream);
301 },
302 [&]() {
303 (void)AAudioStream_getXRunCount(mAaudioStream);
304 },
305 [&]() {
306 (void)AAudioStream_getFramesWritten(mAaudioStream);
307 },
308 [&]() {
309 (void)AAudioStream_getBufferCapacityInFrames(mAaudioStream);
310 },
311 [&]() {
312 (void)AAudioStream_getBufferSizeInFrames(mAaudioStream);
313 },
314 [&]() {
315 (void)AAudioStream_isMMapUsed(mAaudioStream);
316 },
317 });
318 AAudioapi();
319 }
320 AAudioStream_release(mAaudioStream);
321 }
322
deInit()323 void LibAaudioFuzzer::deInit() {
324 if (mAaudioBuilder) {
325 AAudioStreamBuilder_delete(mAaudioBuilder);
326 }
327 if (mAaudioStream) {
328 AAudioStream_close(mAaudioStream);
329 }
330 }
331
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)332 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
333 LibAaudioFuzzer libAaudioFuzzer;
334 if (libAaudioFuzzer.init()) {
335 libAaudioFuzzer.process(data, size);
336 }
337 return 0;
338 }
339