• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <StagefrightMetadataRetriever.h>
19 #include <binder/ProcessState.h>
20 #include <datasource/FileSource.h>
21 #include <media/IMediaHTTPService.h>
22 #include <media/stagefright/foundation/MediaDefs.h>
23 #include <media/stagefright/foundation/base64.h>
24 
25 #include <fuzzer/FuzzedDataProvider.h>
26 
27 using namespace std;
28 using namespace android;
29 
30 const char *kMimeTypes[] = {MEDIA_MIMETYPE_IMAGE_JPEG,         MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
31                             MEDIA_MIMETYPE_VIDEO_VP8,          MEDIA_MIMETYPE_VIDEO_VP9,
32                             MEDIA_MIMETYPE_VIDEO_AV1,          MEDIA_MIMETYPE_VIDEO_AVC,
33                             MEDIA_MIMETYPE_VIDEO_HEVC,         MEDIA_MIMETYPE_VIDEO_MPEG4,
34                             MEDIA_MIMETYPE_VIDEO_H263,         MEDIA_MIMETYPE_VIDEO_MPEG2,
35                             MEDIA_MIMETYPE_VIDEO_RAW,          MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
36                             MEDIA_MIMETYPE_VIDEO_SCRAMBLED,    MEDIA_MIMETYPE_VIDEO_DIVX,
37                             MEDIA_MIMETYPE_VIDEO_DIVX3,        MEDIA_MIMETYPE_VIDEO_XVID,
38                             MEDIA_MIMETYPE_VIDEO_MJPEG,        MEDIA_MIMETYPE_AUDIO_AMR_NB,
39                             MEDIA_MIMETYPE_AUDIO_AMR_WB,       MEDIA_MIMETYPE_AUDIO_MPEG,
40                             MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
41                             MEDIA_MIMETYPE_AUDIO_MIDI,         MEDIA_MIMETYPE_AUDIO_AAC,
42                             MEDIA_MIMETYPE_AUDIO_QCELP,        MEDIA_MIMETYPE_AUDIO_VORBIS,
43                             MEDIA_MIMETYPE_AUDIO_OPUS,         MEDIA_MIMETYPE_AUDIO_G711_ALAW,
44                             MEDIA_MIMETYPE_AUDIO_G711_MLAW,    MEDIA_MIMETYPE_AUDIO_RAW,
45                             MEDIA_MIMETYPE_AUDIO_FLAC,         MEDIA_MIMETYPE_AUDIO_AAC_ADTS,
46                             MEDIA_MIMETYPE_AUDIO_MSGSM,        MEDIA_MIMETYPE_AUDIO_AC3,
47                             MEDIA_MIMETYPE_AUDIO_EAC3,         MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
48                             MEDIA_MIMETYPE_AUDIO_AC4,          MEDIA_MIMETYPE_AUDIO_SCRAMBLED,
49                             MEDIA_MIMETYPE_AUDIO_ALAC,         MEDIA_MIMETYPE_AUDIO_WMA,
50                             MEDIA_MIMETYPE_AUDIO_MS_ADPCM,     MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM,
51                             MEDIA_MIMETYPE_CONTAINER_MPEG4,    MEDIA_MIMETYPE_CONTAINER_WAV,
52                             MEDIA_MIMETYPE_CONTAINER_OGG,      MEDIA_MIMETYPE_CONTAINER_MATROSKA,
53                             MEDIA_MIMETYPE_CONTAINER_MPEG2TS,  MEDIA_MIMETYPE_CONTAINER_AVI,
54                             MEDIA_MIMETYPE_CONTAINER_MPEG2PS,  MEDIA_MIMETYPE_CONTAINER_HEIF,
55                             MEDIA_MIMETYPE_TEXT_3GPP,          MEDIA_MIMETYPE_TEXT_SUBRIP,
56                             MEDIA_MIMETYPE_TEXT_VTT,           MEDIA_MIMETYPE_TEXT_CEA_608,
57                             MEDIA_MIMETYPE_TEXT_CEA_708,       MEDIA_MIMETYPE_DATA_TIMED_ID3};
58 
59 class MetadataRetrieverFuzzer {
60    public:
MetadataRetrieverFuzzer(const uint8_t * data,size_t size)61     MetadataRetrieverFuzzer(const uint8_t *data, size_t size)
62         : mFdp(data, size),
63           mMdRetriever(new StagefrightMetadataRetriever()),
64           mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)) {}
~MetadataRetrieverFuzzer()65     ~MetadataRetrieverFuzzer() { close(mDataSourceFd); }
66     bool setDataSource(const uint8_t *data, size_t size);
67     void getData();
68 
69    private:
70     FuzzedDataProvider mFdp;
71     sp<StagefrightMetadataRetriever> mMdRetriever = nullptr;
72     const int32_t mDataSourceFd;
73 };
74 
getData()75 void MetadataRetrieverFuzzer::getData() {
76     int64_t timeUs = mFdp.ConsumeIntegral<int64_t>();
77     int32_t option = mFdp.ConsumeIntegral<int32_t>();
78     int32_t colorFormat = mFdp.ConsumeIntegral<int32_t>();
79     bool metaOnly = mFdp.ConsumeBool();
80     mMdRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly);
81 
82     int32_t index = mFdp.ConsumeIntegral<int32_t>();
83     colorFormat = mFdp.ConsumeIntegral<int32_t>();
84     metaOnly = mFdp.ConsumeBool();
85     bool thumbnail = mFdp.ConsumeBool();
86     mMdRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
87 
88     index = mFdp.ConsumeIntegral<int32_t>();
89     colorFormat = mFdp.ConsumeIntegral<int32_t>();
90     int32_t left = mFdp.ConsumeIntegral<int32_t>();
91     int32_t top = mFdp.ConsumeIntegral<int32_t>();
92     int32_t right = mFdp.ConsumeIntegral<int32_t>();
93     int32_t bottom = mFdp.ConsumeIntegral<int32_t>();
94     mMdRetriever->getImageRectAtIndex(index, colorFormat, left, top, right, bottom);
95 
96     index = mFdp.ConsumeIntegral<int32_t>();
97     colorFormat = mFdp.ConsumeIntegral<int32_t>();
98     metaOnly = mFdp.ConsumeBool();
99     mMdRetriever->getFrameAtIndex(index, colorFormat, metaOnly);
100 
101     mMdRetriever->extractAlbumArt();
102 
103     int32_t keyCode = mFdp.ConsumeIntegral<int32_t>();
104     mMdRetriever->extractMetadata(keyCode);
105 }
106 
setDataSource(const uint8_t * data,size_t size)107 bool MetadataRetrieverFuzzer::setDataSource(const uint8_t *data, size_t size) {
108     status_t status = -1;
109 
110     enum DataSourceChoice {FromHttp, FromFd, FromFileSource, kMaxValue = FromFileSource};
111     switch (mFdp.ConsumeEnum<DataSourceChoice>()) {
112         case FromHttp: {
113             KeyedVector<String8, String8> mHeaders;
114             mHeaders.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
115                          String8(mFdp.ConsumeRandomLengthString().c_str()));
116 
117             uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, size);
118             vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
119 
120             string uri("data:");
121             uri += ";base64,";
122             AString out;
123             encodeBase64(uriSuffix.data(), uriSuffix.size(), &out);
124             uri += out.c_str();
125             status = mMdRetriever->setDataSource(nullptr /*httpService*/, uri.c_str(), &mHeaders);
126             break;
127         }
128         case FromFd: {
129             write(mDataSourceFd, data, size);
130 
131             status = mMdRetriever->setDataSource(mDataSourceFd, 0, size);
132             break;
133         }
134         case FromFileSource: {
135             write(mDataSourceFd, data, size);
136 
137             sp<DataSource> dataSource = new FileSource(dup(mDataSourceFd), 0, size);
138             status = mMdRetriever->setDataSource(dataSource, mFdp.PickValueInArray(kMimeTypes));
139             break;
140         }
141     }
142 
143     if (status != 0) {
144         return false;
145     }
146     return true;
147 }
148 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)149 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
150     MetadataRetrieverFuzzer mrtFuzzer(data, size);
151     ProcessState::self()->startThreadPool();
152     if (mrtFuzzer.setDataSource(data, size)) {
153         mrtFuzzer.getData();
154     }
155     return 0;
156 }
157