• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 #include <android/binder_process.h>
17 #include <fcntl.h>
18 #include <fuzzer/FuzzedDataProvider.h>
19 #include <media/NdkMediaMuxer.h>
20 #include <sys/mman.h>
21 #include <unistd.h>
22 
23 const std::string kMuxerFile = "mediaMuxer";
24 const std::string kAppendFile = "mediaAppend";
25 constexpr size_t kMinBytes = 0;
26 constexpr size_t kMaxBytes = 1000;
27 constexpr size_t kMinChoice = 0;
28 constexpr size_t kMaxChoice = 7;
29 constexpr size_t kMaxStringLength = 20;
30 constexpr size_t kOffset = 0;
31 
32 constexpr OutputFormat kOutputFormat[] = {AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4,
33                                           AMEDIAMUXER_OUTPUT_FORMAT_WEBM,
34                                           AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP};
35 constexpr AppendMode kAppendMode[] = {AMEDIAMUXER_APPEND_IGNORE_LAST_VIDEO_GOP,
36                                       AMEDIAMUXER_APPEND_TO_EXISTING_DATA};
37 
38 const std::string kAudioMimeType[] = {"audio/3gpp", "audio/amr-wb", "audio/mp4a-latm",
39                                       "audio/flac", "audio/vorbis", "audio/opus"};
40 
41 const std::string kVideoMimeType[] = {"video/x-vnd.on2.vp8", "video/x-vnd.on2.vp9", "video/av01",
42                                       "video/avc",           "video/hevc",          "video/mp4v-es",
43                                       "video/3gpp"};
44 
getSampleAudioFormat(FuzzedDataProvider & fdp,AMediaFormat * format)45 void getSampleAudioFormat(FuzzedDataProvider& fdp, AMediaFormat* format) {
46     std::string mimeType = fdp.ConsumeBool() ? fdp.ConsumeRandomLengthString(kMaxStringLength)
47                                              : fdp.PickValueInArray(kAudioMimeType);
48     AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mimeType.c_str());
49     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, fdp.ConsumeIntegral<int32_t>());
50     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, fdp.ConsumeIntegral<int32_t>());
51     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, fdp.ConsumeIntegral<int32_t>());
52     AMediaFormat_setInt64(format, AMEDIAFORMAT_KEY_DURATION, fdp.ConsumeIntegral<int64_t>());
53 }
54 
getSampleVideoFormat(FuzzedDataProvider & fdp,AMediaFormat * format)55 void getSampleVideoFormat(FuzzedDataProvider& fdp, AMediaFormat* format) {
56     std::string mimeType = fdp.ConsumeBool() ? fdp.ConsumeRandomLengthString(kMaxStringLength)
57                                              : fdp.PickValueInArray(kAudioMimeType);
58     AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mimeType.c_str());
59     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, fdp.ConsumeIntegral<int32_t>());
60     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, fdp.ConsumeIntegral<int32_t>());
61     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, fdp.ConsumeIntegral<int32_t>());
62     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, fdp.ConsumeIntegral<int32_t>());
63     AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL,
64                           fdp.ConsumeFloatingPoint<float>());
65     AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_CAPTURE_RATE, fdp.ConsumeFloatingPoint<float>());
66     AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, fdp.ConsumeIntegral<int32_t>());
67 }
68 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)69 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
70     /**
71      * Create a threadpool for incoming binder transactions,
72      * without this muxer results in a DoS after few instances.
73      */
74     ABinderProcess_startThreadPool();
75     FuzzedDataProvider fdp(data, size);
76     /**
77      * memfd_create() creates an anonymous file and returns a file
78      * descriptor that refers to it. MFD_ALLOW_SEALING allow sealing
79      * operations on this file.
80      */
81     int32_t fd = -1;
82     AMediaMuxer* muxer = nullptr;
83     if (fdp.ConsumeBool()) {
84         fd = memfd_create(kMuxerFile.c_str(), MFD_ALLOW_SEALING);
85         muxer = AMediaMuxer_new(fd, fdp.ConsumeBool()
86                                             ? fdp.PickValueInArray(kOutputFormat)
87                                             : (OutputFormat)fdp.ConsumeIntegral<int32_t>());
88     } else {
89         fd = memfd_create(kAppendFile.c_str(), MFD_ALLOW_SEALING);
90         std::vector<uint8_t> appendData =
91                 fdp.ConsumeBytes<uint8_t>(fdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
92         write(fd, appendData.data(), appendData.size());
93         muxer = AMediaMuxer_append(fd, fdp.PickValueInArray(kAppendMode) /* mode */);
94     }
95     if (!muxer) {
96         close(fd);
97         return 0;
98     }
99     AMediaFormat* mediaFormat = nullptr;
100     ssize_t trackIdx = 0;
101     while (fdp.remaining_bytes()) {
102         int32_t kSwitchChoice = fdp.ConsumeIntegralInRange<int32_t>(kMinChoice, kMaxChoice);
103         switch (kSwitchChoice) {
104             case 0: {
105                 AMediaMuxer_setLocation(muxer, fdp.ConsumeFloatingPoint<float>() /* latitude */,
106                                         fdp.ConsumeFloatingPoint<float>() /* longitude */);
107                 break;
108             }
109             case 1: {
110                 AMediaMuxer_setOrientationHint(muxer, fdp.ConsumeIntegral<int32_t>() /* degrees */);
111                 break;
112             }
113             case 2: {
114                 AMediaMuxer_start(muxer);
115                 break;
116             }
117             case 3: {
118                 AMediaMuxer_stop(muxer);
119                 break;
120             }
121             case 4: {
122                 AMediaMuxer_getTrackCount(muxer);
123                 break;
124             }
125             case 5: {
126                 AMediaFormat* getFormat =
127                         AMediaMuxer_getTrackFormat(muxer, fdp.ConsumeIntegral<size_t>() /* idx */);
128                 AMediaFormat_delete(getFormat);
129                 break;
130             }
131             case 6: {
132                 mediaFormat = AMediaFormat_new();
133                 fdp.ConsumeBool() ? getSampleAudioFormat(fdp, mediaFormat)
134                                   : getSampleVideoFormat(fdp, mediaFormat);
135                 trackIdx = AMediaMuxer_addTrack(muxer, mediaFormat);
136                 AMediaFormat_delete(mediaFormat);
137                 break;
138             }
139             default: {
140                 std::vector<uint8_t> sampleData = fdp.ConsumeBytes<uint8_t>(
141                         fdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
142                 AMediaCodecBufferInfo codecBuffer;
143                 codecBuffer.size = sampleData.size();
144                 codecBuffer.offset = kOffset;
145                 codecBuffer.presentationTimeUs = fdp.ConsumeIntegral<int64_t>();
146                 codecBuffer.flags = fdp.ConsumeIntegral<uint32_t>();
147                 AMediaMuxer_writeSampleData(
148                         muxer,
149                         fdp.ConsumeBool() ? trackIdx : fdp.ConsumeIntegral<size_t>() /* trackIdx */,
150                         sampleData.data(), &codecBuffer);
151                 break;
152             }
153         }
154     }
155     AMediaMuxer_delete(muxer);
156     close(fd);
157     return 0;
158 }
159