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 <MediaExtractorService.h>
19 #include <MediaPlayerService.h>
20 #include <StagefrightMetadataRetriever.h>
21 #include <binder/ProcessState.h>
22 #include <datasource/FileSource.h>
23 #include <media/IMediaHTTPService.h>
24 #include <media/stagefright/foundation/MediaDefs.h>
25 #include <media/stagefright/foundation/base64.h>
26 
27 #include <fuzzer/FuzzedDataProvider.h>
28 
29 using namespace std;
30 using namespace android;
31 
32 const char *kMimeTypes[] = {MEDIA_MIMETYPE_IMAGE_JPEG,         MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
33                             MEDIA_MIMETYPE_VIDEO_VP8,          MEDIA_MIMETYPE_VIDEO_VP9,
34                             MEDIA_MIMETYPE_VIDEO_AV1,          MEDIA_MIMETYPE_VIDEO_AVC,
35                             MEDIA_MIMETYPE_VIDEO_HEVC,         MEDIA_MIMETYPE_VIDEO_MPEG4,
36                             MEDIA_MIMETYPE_VIDEO_H263,         MEDIA_MIMETYPE_VIDEO_MPEG2,
37                             MEDIA_MIMETYPE_VIDEO_RAW,          MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
38                             MEDIA_MIMETYPE_VIDEO_SCRAMBLED,    MEDIA_MIMETYPE_VIDEO_DIVX,
39                             MEDIA_MIMETYPE_VIDEO_DIVX3,        MEDIA_MIMETYPE_VIDEO_XVID,
40                             MEDIA_MIMETYPE_VIDEO_MJPEG,        MEDIA_MIMETYPE_AUDIO_AMR_NB,
41                             MEDIA_MIMETYPE_AUDIO_AMR_WB,       MEDIA_MIMETYPE_AUDIO_MPEG,
42                             MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
43                             MEDIA_MIMETYPE_AUDIO_MIDI,         MEDIA_MIMETYPE_AUDIO_AAC,
44                             MEDIA_MIMETYPE_AUDIO_QCELP,        MEDIA_MIMETYPE_AUDIO_VORBIS,
45                             MEDIA_MIMETYPE_AUDIO_OPUS,         MEDIA_MIMETYPE_AUDIO_G711_ALAW,
46                             MEDIA_MIMETYPE_AUDIO_G711_MLAW,    MEDIA_MIMETYPE_AUDIO_RAW,
47                             MEDIA_MIMETYPE_AUDIO_FLAC,         MEDIA_MIMETYPE_AUDIO_AAC_ADTS,
48                             MEDIA_MIMETYPE_AUDIO_MSGSM,        MEDIA_MIMETYPE_AUDIO_AC3,
49                             MEDIA_MIMETYPE_AUDIO_EAC3,         MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
50                             MEDIA_MIMETYPE_AUDIO_AC4,          MEDIA_MIMETYPE_AUDIO_SCRAMBLED,
51                             MEDIA_MIMETYPE_AUDIO_ALAC,         MEDIA_MIMETYPE_AUDIO_WMA,
52                             MEDIA_MIMETYPE_AUDIO_MS_ADPCM,     MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM,
53                             MEDIA_MIMETYPE_CONTAINER_MPEG4,    MEDIA_MIMETYPE_CONTAINER_WAV,
54                             MEDIA_MIMETYPE_CONTAINER_OGG,      MEDIA_MIMETYPE_CONTAINER_MATROSKA,
55                             MEDIA_MIMETYPE_CONTAINER_MPEG2TS,  MEDIA_MIMETYPE_CONTAINER_AVI,
56                             MEDIA_MIMETYPE_CONTAINER_MPEG2PS,  MEDIA_MIMETYPE_CONTAINER_HEIF,
57                             MEDIA_MIMETYPE_TEXT_3GPP,          MEDIA_MIMETYPE_TEXT_SUBRIP,
58                             MEDIA_MIMETYPE_TEXT_VTT,           MEDIA_MIMETYPE_TEXT_CEA_608,
59                             MEDIA_MIMETYPE_TEXT_CEA_708,       MEDIA_MIMETYPE_DATA_TIMED_ID3,
60                             MEDIA_MIMETYPE_IMAGE_AVIF,         MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1,
61                             MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1,   MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3,
62                             MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4,  MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3,
63                             MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4,  MEDIA_MIMETYPE_AUDIO_DTS,
64                             MEDIA_MIMETYPE_AUDIO_DTS_HD,       MEDIA_MIMETYPE_AUDIO_DTS_HD_MA,
65                             MEDIA_MIMETYPE_AUDIO_DTS_UHD,      MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1,
66                             MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2,   MEDIA_MIMETYPE_AUDIO_EVRC,
67                             MEDIA_MIMETYPE_AUDIO_EVRCB,        MEDIA_MIMETYPE_AUDIO_EVRCWB,
68                             MEDIA_MIMETYPE_AUDIO_EVRCNW,       MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS,
69                             MEDIA_MIMETYPE_AUDIO_APTX,         MEDIA_MIMETYPE_AUDIO_DRA,
70                             MEDIA_MIMETYPE_AUDIO_DOLBY_MAT,    MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD,
71                             MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_1_0,MEDIA_MIMETYPE_AUDIO_AAC_MP4,
72                             MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_0,MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_1,
73                             MEDIA_MIMETYPE_AUDIO_AAC_MAIN,     MEDIA_MIMETYPE_AUDIO_AAC_LC,
74                             MEDIA_MIMETYPE_AUDIO_AAC_SSR,      MEDIA_MIMETYPE_AUDIO_AAC_LTP,
75                             MEDIA_MIMETYPE_AUDIO_AAC_HE_V1,    MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE,
76                             MEDIA_MIMETYPE_AUDIO_AAC_ERLC,     MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN,
77                             MEDIA_MIMETYPE_AUDIO_AAC_HE_V2,    MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1,
78                             MEDIA_MIMETYPE_AUDIO_AAC_XHE,      MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2,
79                             MEDIA_MIMETYPE_AUDIO_AAC_LD,       MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC,
80                             MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP,
81                             MEDIA_MIMETYPE_AUDIO_AAC_ADIF,     MEDIA_MIMETYPE_AUDIO_IEC60958,
82                             MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC,MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD,
83                             MEDIA_MIMETYPE_AUDIO_AAC_ELD,      MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1,
84                             MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE, MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC,
85                             MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD, MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2,
86                             MEDIA_MIMETYPE_AUDIO_IEC61937,
87                             MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE,};
88 
89 constexpr size_t kMaxSize = 100;
90 
91 class MetadataRetrieverFuzzer {
92    public:
MetadataRetrieverFuzzer(const uint8_t * data,size_t size)93     MetadataRetrieverFuzzer(const uint8_t *data, size_t size)
94         : mFdp(data, size), mMdRetriever(new StagefrightMetadataRetriever()) {}
95     bool setDataSource(const uint8_t *data, size_t size);
96     void getData();
97 
98    private:
99     FuzzedDataProvider mFdp;
100     sp<StagefrightMetadataRetriever> mMdRetriever = nullptr;
101     int32_t mDataSourceFd;
102 };
103 
getData()104 void MetadataRetrieverFuzzer::getData() {
105     while (mFdp.remaining_bytes()) {
106         auto invokeMediaApi = mFdp.PickValueInArray<const std::function<void()>>({
107                 [&]() {
108                     mMdRetriever->getFrameAtTime(mFdp.ConsumeIntegral<int64_t>() /* timeUs */,
109                                                  mFdp.ConsumeIntegral<int32_t>() /* option */,
110                                                  mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
111                                                  mFdp.ConsumeBool() /* metaOnly */);
112                 },
113                 [&]() {
114                     mMdRetriever->getImageAtIndex(mFdp.ConsumeIntegral<int32_t>() /* index */,
115                                                   mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
116                                                   mFdp.ConsumeBool() /* metaOnly */,
117                                                   mFdp.ConsumeBool() /* thumbnail */);
118                 },
119                 [&]() {
120                     mMdRetriever->getImageRectAtIndex(
121                             mFdp.ConsumeIntegral<int32_t>() /* index */,
122                             mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
123                             mFdp.ConsumeIntegral<int32_t>() /* left */,
124                             mFdp.ConsumeIntegral<int32_t>() /* top */,
125                             mFdp.ConsumeIntegral<int32_t>() /* right */,
126                             mFdp.ConsumeIntegral<int32_t>() /* bottom */);
127                 },
128                 [&]() {
129                     mMdRetriever->getFrameAtIndex(mFdp.ConsumeIntegral<int32_t>() /* index */,
130                                                   mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
131                                                   mFdp.ConsumeBool() /* metaOnly */);
132                 },
133                 [&]() { mMdRetriever->extractAlbumArt(); },
134                 [&]() {
135                     mMdRetriever->extractMetadata(mFdp.ConsumeIntegral<int32_t>() /* keyCode */);
136                 },
137         });
138         invokeMediaApi();
139     }
140 }
141 
setDataSource(const uint8_t * data,size_t size)142 bool MetadataRetrieverFuzzer::setDataSource(const uint8_t *data, size_t size) {
143     status_t status = -1;
144     std::unique_ptr<std::FILE, decltype(&fclose)> fp(tmpfile(), &fclose);
145     mDataSourceFd = fileno(fp.get());
146     if (mDataSourceFd < 0) {
147         return false;
148     }
149 
150     enum DataSourceChoice {FromHttp, FromFd, FromFileSource, kMaxValue = FromFileSource};
151     switch (mFdp.ConsumeEnum<DataSourceChoice>()) {
152         case FromHttp: {
153             KeyedVector<String8, String8> mHeaders;
154             mHeaders.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
155                          String8(mFdp.ConsumeRandomLengthString().c_str()));
156 
157             uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, min(kMaxSize,size));
158             vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
159 
160             string uri("data:");
161             uri += ";base64,";
162             AString out;
163             encodeBase64(uriSuffix.data(), uriSuffix.size(), &out);
164             uri += out.c_str();
165             status = mMdRetriever->setDataSource(nullptr /*httpService*/, uri.c_str(), &mHeaders);
166             break;
167         }
168         case FromFd: {
169             write(mDataSourceFd, data, size);
170 
171             status = mMdRetriever->setDataSource(mDataSourceFd, 0, size);
172             break;
173         }
174         case FromFileSource: {
175             write(mDataSourceFd, data, size);
176 
177             sp<DataSource> dataSource = new FileSource(dup(mDataSourceFd), 0, size);
178             status = mMdRetriever->setDataSource(dataSource, mFdp.PickValueInArray(kMimeTypes));
179             break;
180         }
181     }
182 
183     if (status != 0) {
184         return false;
185     }
186     return true;
187 }
188 
LLVMFuzzerInitialize(int *,char ***)189 extern "C" int LLVMFuzzerInitialize(int* /* argc */, char*** /* argv */) {
190     MediaPlayerService::instantiate();
191     MediaExtractorService::instantiate();
192     return 0;
193 }
194 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)195 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
196     MetadataRetrieverFuzzer mrtFuzzer(data, size);
197     ProcessState::self()->startThreadPool();
198     if (mrtFuzzer.setDataSource(data, size)) {
199         mrtFuzzer.getData();
200     }
201     return 0;
202 }
203