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