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