xref: /aosp_15_r20/frameworks/av/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright 2020 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 <fuzzer/FuzzedDataProvider.h>
18 #include <media/stagefright/MediaMuxer.h>
19 #include <media/stagefright/foundation/ABuffer.h>
20 #include <media/stagefright/foundation/AMessage.h>
21 #include <media/stagefright/foundation/MediaDefs.h>
22 
23 namespace android {
24 const uint8_t kMinSize = 0;
25 const uint8_t kMinTrackCount = 0;
26 
27 enum kBufferFlags { BUFFER_FLAG_SYNCFRAME = 1, BUFFER_FLAG_CODECCONFIG = 2, BUFFER_FLAG_EOS = 4 };
28 
29 constexpr char kMuxerFile[] = "MediaMuxer";
30 
31 const std::string kAudioMimeTypes[] = {
32         MEDIA_MIMETYPE_AUDIO_AMR_NB,
33         MEDIA_MIMETYPE_AUDIO_AMR_WB,
34         MEDIA_MIMETYPE_AUDIO_MPEG,
35         MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
36         MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
37         MEDIA_MIMETYPE_AUDIO_MIDI,
38         MEDIA_MIMETYPE_AUDIO_AAC,
39         MEDIA_MIMETYPE_AUDIO_QCELP,
40         MEDIA_MIMETYPE_AUDIO_VORBIS,
41         MEDIA_MIMETYPE_AUDIO_OPUS,
42         MEDIA_MIMETYPE_AUDIO_G711_ALAW,
43         MEDIA_MIMETYPE_AUDIO_G711_MLAW,
44         MEDIA_MIMETYPE_AUDIO_RAW,
45         MEDIA_MIMETYPE_AUDIO_FLAC,
46         MEDIA_MIMETYPE_AUDIO_AAC_ADTS,
47         MEDIA_MIMETYPE_AUDIO_MSGSM,
48         MEDIA_MIMETYPE_AUDIO_AC3,
49         MEDIA_MIMETYPE_AUDIO_EAC3,
50         MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
51         MEDIA_MIMETYPE_AUDIO_AC4,
52         MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1,
53         MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1,
54         MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3,
55         MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4,
56         MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3,
57         MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4,
58         MEDIA_MIMETYPE_AUDIO_SCRAMBLED,
59         MEDIA_MIMETYPE_AUDIO_ALAC,
60         MEDIA_MIMETYPE_AUDIO_WMA,
61         MEDIA_MIMETYPE_AUDIO_MS_ADPCM,
62         MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM,
63         MEDIA_MIMETYPE_AUDIO_DTS,
64         MEDIA_MIMETYPE_AUDIO_DTS_HD,
65         MEDIA_MIMETYPE_AUDIO_DTS_HD_MA,
66         MEDIA_MIMETYPE_AUDIO_DTS_UHD,
67         MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1,
68         MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2,
69         MEDIA_MIMETYPE_AUDIO_EVRC,
70         MEDIA_MIMETYPE_AUDIO_EVRCB,
71         MEDIA_MIMETYPE_AUDIO_EVRCWB,
72         MEDIA_MIMETYPE_AUDIO_EVRCNW,
73         MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS,
74         MEDIA_MIMETYPE_AUDIO_APTX,
75         MEDIA_MIMETYPE_AUDIO_DRA,
76         MEDIA_MIMETYPE_AUDIO_DOLBY_MAT,
77         MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_1_0,
78         MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_0,
79         MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_1,
80         MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD,
81         MEDIA_MIMETYPE_AUDIO_AAC_MP4,
82         MEDIA_MIMETYPE_AUDIO_AAC_MAIN,
83         MEDIA_MIMETYPE_AUDIO_AAC_LC,
84         MEDIA_MIMETYPE_AUDIO_AAC_SSR,
85         MEDIA_MIMETYPE_AUDIO_AAC_LTP,
86         MEDIA_MIMETYPE_AUDIO_AAC_HE_V1,
87         MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE,
88         MEDIA_MIMETYPE_AUDIO_AAC_ERLC,
89         MEDIA_MIMETYPE_AUDIO_AAC_LD,
90         MEDIA_MIMETYPE_AUDIO_AAC_HE_V2,
91         MEDIA_MIMETYPE_AUDIO_AAC_ELD,
92         MEDIA_MIMETYPE_AUDIO_AAC_XHE,
93         MEDIA_MIMETYPE_AUDIO_AAC_ADIF,
94         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN,
95         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC,
96         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR,
97         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP,
98         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1,
99         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE,
100         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC,
101         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD,
102         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2,
103         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD,
104         MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE,
105         MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC,
106         MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1,
107         MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2,
108         MEDIA_MIMETYPE_AUDIO_IEC61937,
109         MEDIA_MIMETYPE_AUDIO_IEC60958,
110 };
111 
112 const std::string kVideoMimeTypes[] = {
113         MEDIA_MIMETYPE_VIDEO_VP8,       MEDIA_MIMETYPE_VIDEO_VP9,
114         MEDIA_MIMETYPE_VIDEO_AV1,       MEDIA_MIMETYPE_VIDEO_AVC,
115         MEDIA_MIMETYPE_VIDEO_HEVC,      MEDIA_MIMETYPE_VIDEO_MPEG4,
116         MEDIA_MIMETYPE_VIDEO_H263,      MEDIA_MIMETYPE_VIDEO_MPEG2,
117         MEDIA_MIMETYPE_VIDEO_RAW,       MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
118         MEDIA_MIMETYPE_VIDEO_SCRAMBLED, MEDIA_MIMETYPE_VIDEO_DIVX,
119         MEDIA_MIMETYPE_VIDEO_DIVX3,     MEDIA_MIMETYPE_VIDEO_XVID,
120         MEDIA_MIMETYPE_VIDEO_MJPEG,
121 };
122 
getSampleAudioFormat(FuzzedDataProvider & fdp,AMessage * format)123 void getSampleAudioFormat(FuzzedDataProvider& fdp, AMessage* format) {
124     std::string mimeType = fdp.PickValueInArray(kAudioMimeTypes);
125     format->setString("mime", mimeType.c_str(), mimeType.length());
126     format->setInt32("sample-rate", fdp.ConsumeIntegral<int32_t>());
127     format->setInt32("channel-count", fdp.ConsumeIntegral<int32_t>());
128 }
129 
getSampleVideoFormat(FuzzedDataProvider & fdp,AMessage * format)130 void getSampleVideoFormat(FuzzedDataProvider& fdp, AMessage* format) {
131     std::string mimeType = fdp.PickValueInArray(kVideoMimeTypes);
132     format->setString("mime", mimeType.c_str(), mimeType.length());
133     format->setInt32("height", fdp.ConsumeIntegral<int32_t>());
134     format->setInt32("width", fdp.ConsumeIntegral<int32_t>());
135     format->setInt32("time-lapse-fps", fdp.ConsumeIntegral<int32_t>());
136 }
137 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)138 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
139     FuzzedDataProvider fdp(data, size);
140 
141     // memfd_create() creates an anonymous file and returns a file
142     // descriptor that refers to it. MFD_ALLOW_SEALING allows sealing
143     // operations on this file.
144     int32_t fd = memfd_create(kMuxerFile, MFD_ALLOW_SEALING);
145     if (fd == -1) {
146         ALOGE("memfd_create failed: %s", strerror(errno));
147         return 0;
148     }
149 
150     auto outputFormat = (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>(
151             MediaMuxer::OutputFormat::OUTPUT_FORMAT_MPEG_4,
152             MediaMuxer::OutputFormat::OUTPUT_FORMAT_LIST_END);
153 
154     sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, outputFormat);
155     if (mMuxer == nullptr) {
156         close(fd);
157         return 0;
158     }
159 
160     // Used to consume a maximum of 80% of the data to send buffer data to writeSampleData().
161     // This ensures that we don't completely exhaust data and use the rest 20% for fuzzing
162     // of APIs.
163     const size_t kMaxSize = (size * 80) / 100;
164     while (fdp.remaining_bytes()) {
165         auto invokeMediaMuxerAPI = fdp.PickValueInArray<const std::function<void()>>({
166                 [&]() {
167                     // Using 'return' here due to a timeout bug present in OGGWriter.cpp
168                     // (b/310316183).
169                     if (outputFormat == MediaMuxer::OutputFormat::OUTPUT_FORMAT_OGG) {
170                         return;
171                     }
172 
173                     sp<AMessage> format = sp<AMessage>::make();
174                     fdp.ConsumeBool() ? getSampleAudioFormat(fdp, format.get())
175                                       : getSampleVideoFormat(fdp, format.get());
176 
177                     mMuxer->addTrack(fdp.ConsumeBool() ? format : nullptr);
178                 },
179                 [&]() {
180                     mMuxer->setLocation(fdp.ConsumeIntegral<int32_t>() /* latitude */,
181                                         fdp.ConsumeIntegral<int32_t>() /* longitude */);
182                 },
183                 [&]() { mMuxer->setOrientationHint(fdp.ConsumeIntegral<int32_t>() /* degrees */); },
184                 [&]() { mMuxer->start(); },
185                 [&]() {
186                     std::vector<uint8_t> sample = fdp.ConsumeBytes<uint8_t>(
187                             fdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
188                     sp<ABuffer> buffer = sp<ABuffer>::make(sample.data(), sample.size());
189 
190                     size_t offset = fdp.ConsumeIntegralInRange<size_t>(kMinSize, sample.size());
191                     size_t length =
192                             fdp.ConsumeIntegralInRange<size_t>(kMinSize, buffer->size() - offset);
193                     buffer->setRange(offset, length);
194 
195                     sp<AMessage> meta = buffer->meta();
196                     meta->setInt64("sample-file-offset", fdp.ConsumeIntegral<int64_t>());
197                     meta->setInt64("last-sample-index-in-chunk", fdp.ConsumeIntegral<int64_t>());
198 
199                     uint32_t flags = 0;
200                     if (fdp.ConsumeBool()) {
201                         flags |= kBufferFlags::BUFFER_FLAG_SYNCFRAME;
202                     }
203                     if (fdp.ConsumeBool()) {
204                         flags |= kBufferFlags::BUFFER_FLAG_CODECCONFIG;
205                     }
206                     if (fdp.ConsumeBool()) {
207                         flags |= kBufferFlags::BUFFER_FLAG_EOS;
208                     }
209 
210                     size_t trackIndex = fdp.ConsumeBool()
211                                                 ? fdp.ConsumeIntegralInRange<size_t>(
212                                                           kMinTrackCount, mMuxer->getTrackCount())
213                                                 : fdp.ConsumeIntegral<size_t>();
214                     int64_t timeUs = fdp.ConsumeIntegral<int64_t>();
215                     mMuxer->writeSampleData(fdp.ConsumeBool() ? buffer : nullptr, trackIndex,
216                                             timeUs, flags);
217                 },
218                 [&]() {
219                     mMuxer->getTrackFormat(
220                             fdp.ConsumeBool() ? fdp.ConsumeIntegralInRange<size_t>(
221                                                         kMinTrackCount, mMuxer->getTrackCount())
222                                               : fdp.ConsumeIntegral<size_t>() /* idx */);
223                 },
224                 [&]() { mMuxer->stop(); },
225         });
226 
227         invokeMediaMuxerAPI();
228     }
229 
230     close(fd);
231     return 0;
232 }
233 } // namespace android
234