1 /*
2  * Copyright (C) 2019 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 <android-base/macros.h>
18 #include <audio_utils/primitives.h>
19 #include <audio_utils/sndfile.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <inttypes.h>
23 #include <math.h>
24 #include <media/AudioBufferProvider.h>
25 #include <media/AudioResampler.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/mman.h>
32 #include <sys/stat.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include <utils/Vector.h>
36 
37 #include <memory>
38 
39 using namespace android;
40 
41 const int MAX_FRAMES = 10;
42 const int MIN_FREQ = 1e3;
43 const int MAX_FREQ = 100e3;
44 
45 const AudioResampler::src_quality qualities[] = {
46     AudioResampler::DEFAULT_QUALITY,
47     AudioResampler::LOW_QUALITY,
48     AudioResampler::MED_QUALITY,
49     AudioResampler::HIGH_QUALITY,
50     AudioResampler::VERY_HIGH_QUALITY,
51     AudioResampler::DYN_LOW_QUALITY,
52     AudioResampler::DYN_MED_QUALITY,
53     AudioResampler::DYN_HIGH_QUALITY,
54 };
55 
56 class Provider : public AudioBufferProvider {
57   const void* mAddr;        // base address
58   const size_t mNumFrames;  // total frames
59   const size_t mFrameSize;  // size of each frame in bytes
60   size_t mNextFrame;        // index of next frame to provide
61   size_t mUnrel;            // number of frames not yet released
62  public:
Provider(const void * addr,size_t frames,size_t frameSize)63   Provider(const void* addr, size_t frames, size_t frameSize)
64       : mAddr(addr),
65         mNumFrames(frames),
66         mFrameSize(frameSize),
67         mNextFrame(0),
68         mUnrel(0) {}
getNextBuffer(Buffer * buffer)69   status_t getNextBuffer(Buffer* buffer) override {
70     if (buffer->frameCount > mNumFrames - mNextFrame) {
71       buffer->frameCount = mNumFrames - mNextFrame;
72     }
73     mUnrel = buffer->frameCount;
74     if (buffer->frameCount > 0) {
75       buffer->raw = (char*)mAddr + mFrameSize * mNextFrame;
76       return NO_ERROR;
77     } else {
78       buffer->raw = nullptr;
79       return NOT_ENOUGH_DATA;
80     }
81   }
releaseBuffer(Buffer * buffer)82   virtual void releaseBuffer(Buffer* buffer) {
83     if (buffer->frameCount > mUnrel) {
84       mNextFrame += mUnrel;
85       mUnrel = 0;
86     } else {
87       mNextFrame += buffer->frameCount;
88       mUnrel -= buffer->frameCount;
89     }
90     buffer->frameCount = 0;
91     buffer->raw = nullptr;
92   }
reset()93   void reset() { mNextFrame = 0; }
94 };
95 
chooseFormat(AudioResampler::src_quality quality,uint8_t input_byte)96 audio_format_t chooseFormat(AudioResampler::src_quality quality,
97                             uint8_t input_byte) {
98   switch (quality) {
99     case AudioResampler::DYN_LOW_QUALITY:
100     case AudioResampler::DYN_MED_QUALITY:
101     case AudioResampler::DYN_HIGH_QUALITY:
102       if (input_byte % 2) {
103         return AUDIO_FORMAT_PCM_FLOAT;
104       }
105       FALLTHROUGH_INTENDED;
106     default:
107       return AUDIO_FORMAT_PCM_16_BIT;
108   }
109 }
110 
parseValue(const uint8_t * src,int index,void * dst,size_t size)111 int parseValue(const uint8_t* src, int index, void* dst, size_t size) {
112   memcpy(dst, &src[index], size);
113   return size;
114 }
115 
validFreq(int freq)116 bool validFreq(int freq) { return freq > MIN_FREQ && freq < MAX_FREQ; }
117 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)118 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
119   int input_freq = 0;
120   int output_freq = 0;
121   int input_channels = 0;
122 
123   float left_volume = 0;
124   float right_volume = 0;
125 
126   size_t metadata_size = 2 + 3 * sizeof(int) + 2 * sizeof(float);
127   if (size < metadata_size) {
128     // not enough data to set options
129     return 0;
130   }
131 
132   AudioResampler::src_quality quality = qualities[data[0] % 8];
133   audio_format_t format = chooseFormat(quality, data[1]);
134 
135   int index = 2;
136 
137   index += parseValue(data, index, &input_freq, sizeof(int));
138   index += parseValue(data, index, &output_freq, sizeof(int));
139   index += parseValue(data, index, &input_channels, sizeof(int));
140 
141   index += parseValue(data, index, &left_volume, sizeof(float));
142   index += parseValue(data, index, &right_volume, sizeof(float));
143 
144   if (!validFreq(input_freq) || !validFreq(output_freq)) {
145     // sampling frequencies must be reasonable
146     return 0;
147   }
148 
149   if (input_channels < 1 ||
150       input_channels > (quality < AudioResampler::DYN_LOW_QUALITY ? 2 : 8)) {
151     // invalid number of input channels
152     return 0;
153   }
154 
155   size_t single_channel_size =
156       format == AUDIO_FORMAT_PCM_FLOAT ? sizeof(float) : sizeof(int16_t);
157   size_t input_frame_size = single_channel_size * input_channels;
158   size_t input_size = size - metadata_size;
159   uint8_t input_data[input_size];
160   memcpy(input_data, &data[metadata_size], input_size);
161 
162   size_t input_frames = input_size / input_frame_size;
163   if (input_frames > MAX_FRAMES) {
164     return 0;
165   }
166 
167   Provider provider(input_data, input_frames, input_frame_size);
168 
169   std::unique_ptr<AudioResampler> resampler(
170       AudioResampler::create(format, input_channels, output_freq, quality));
171 
172   resampler->setSampleRate(input_freq);
173   resampler->setVolume(left_volume, right_volume);
174 
175   // output is at least stereo samples
176   int output_channels = input_channels > 2 ? input_channels : 2;
177   size_t output_frame_size = output_channels * sizeof(int32_t);
178   size_t output_frames = (input_frames * output_freq) / input_freq;
179   size_t output_size = output_frames * output_frame_size;
180 
181   uint8_t output_data[output_size];
182   for (size_t i = 0; i < output_frames; i++) {
183     memset(output_data, 0, output_size);
184     resampler->resample((int*)output_data, i, &provider);
185   }
186 
187   return 0;
188 }
189