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