xref: /aosp_15_r20/frameworks/av/media/libstagefright/rtsp/fuzzer/packet_source_fuzzer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2023 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 <fuzzer/FuzzedDataProvider.h>
17 #include <media/stagefright/foundation/AString.h>
18 #include <media/stagefright/foundation/base64.h>
19 #include <media/stagefright/rtsp/APacketSource.h>
20 #include <media/stagefright/rtsp/ASessionDescription.h>
21 
22 using namespace android;
23 
24 static constexpr int32_t kMinValue = 0;
25 static constexpr int32_t kMaxIPAddress = 255;
26 static constexpr int32_t kMaxFmt = 255;
27 static constexpr int32_t kMinAPICase = 0;
28 static constexpr int32_t kMaxPacketSourceAPI = 5;
29 static constexpr size_t kMinIndex = 1;
30 static constexpr size_t kMaxCodecConfigs = 4;
31 
32 std::string kCodecs[] = {"opus",        "ISAC",         "VP8",
33                          "google-data", "G722",         "PCMU",
34                          "PCMA",        "CN",           "telephone-event",
35                          "VP9",         "red",          "ulpfec",
36                          "rtx",         "H264",         "iLBC",
37                          "H261",        "MPV",          "H263",
38                          "AMR",         "AC3",          "G723",
39                          "G729A",       "H264",         "MP4V-ES",
40                          "H265",        "H263-2000",    "H263-1998",
41                          "AMR",         "AMR-WB",       "MP4A-LATM",
42                          "MP2T",        "mpeg4-generic"};
43 
44 std::string kFmtp[] = {"br=",
45                        "bw=",
46                        "ch-aw-recv=",
47                        "mode-change-capability=",
48                        "max-red =",
49                        "octet-align=",
50                        "mode-change-capability=",
51                        "max-red=",
52                        "profile-level-id=",
53                        "packetization-mode=",
54                        "profile=",
55                        "level=",
56                        "apt=",
57                        "annexb=",
58                        "protocol=",
59                        "streamtype=",
60                        "mode=",
61                        "sizelength=",
62                        "indexlength=",
63                        "indexdeltalength=",
64                        "minptime=",
65                        "useinbandfec=",
66                        "maxplaybackrate=",
67                        "stereo=",
68                        "level-asymmetry-allowed=",
69                        "max-fs=",
70                        "max-fr="};
71 
72 std::string kCodecConfigString[kMaxCodecConfigs][2] = {{"H264", "profile-level-id="},
73                                                        {"MP4A-LATM", "config="},
74                                                        {"MP4V-ES", "config="},
75                                                        {"mpeg4-generic", "mode="}};
76 
77 class ASessionPacketFuzzer {
78   public:
ASessionPacketFuzzer(const uint8_t * data,size_t size)79     ASessionPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
80     void process();
81 
82   private:
83     FuzzedDataProvider mFdp;
84 };
85 
checkFormatSupport(const std::string & codec,const std::string & format)86 bool checkFormatSupport(const std::string& codec, const std::string& format) {
87     for (int i = 0; i < kMaxCodecConfigs; ++i) {
88         if (codec == kCodecConfigString[i][0]) {
89             if (format == kCodecConfigString[i][1]) {
90                 return true;
91             } else {
92                 return false;
93             }
94         }
95     }
96     return true;
97 }
98 
process()99 void ASessionPacketFuzzer::process() {
100     AString inputString;
101     const sp<ASessionDescription> sessionPacket = sp<ASessionDescription>::make();
102     std::string codec = mFdp.PickValueInArray(kCodecs);
103     std::string ipAddress =
104             std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxIPAddress)) + "." +
105             std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxIPAddress)) + "." +
106             std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxIPAddress)) + "." + "0";
107     std::string format = mFdp.PickValueInArray(kFmtp);
108     std::string fmptStr = format + std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxFmt)) +
109                           ";" + mFdp.PickValueInArray(kFmtp) +
110                           std::to_string(mFdp.ConsumeIntegralInRange(kMinValue, kMaxFmt));
111     sessionPacket->SDPStringFactory(
112             inputString, ipAddress.c_str() /* ip */, mFdp.ConsumeBool() /* isAudio */,
113             mFdp.ConsumeIntegral<unsigned int>() /* port */,
114             mFdp.ConsumeIntegral<unsigned int>() /* payloadType */,
115             mFdp.ConsumeIntegral<unsigned int>() /* as */, codec.c_str(), /* codec */
116             fmptStr.c_str() /* fmtp */, mFdp.ConsumeIntegral<int32_t>() /* width */,
117             mFdp.ConsumeIntegral<int32_t>() /* height */,
118             mFdp.ConsumeIntegral<int32_t>() /* cvoExtMap */);
119     sessionPacket->setTo(inputString.c_str(), inputString.size());
120     size_t trackSize = sessionPacket->countTracks();
121     AString desc = nullptr;
122     while (mFdp.remaining_bytes()) {
123         int32_t packetSourceAPI =
124                 mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxPacketSourceAPI);
125         switch (packetSourceAPI) {
126             case 0: {
127                 unsigned long payload = 0;
128                 AString params = nullptr;
129                 sessionPacket->getFormatType(mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1),
130                                              &payload, &desc, &params);
131                 break;
132             }
133             case 1: {
134                 int32_t width, height;
135                 unsigned long payload = mFdp.ConsumeIntegral<unsigned long>();
136                 sessionPacket->getDimensions(mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1),
137                                              payload, &width, &height);
138                 break;
139             }
140             case 2: {
141                 int32_t cvoExtMap = mFdp.ConsumeIntegral<int32_t>();
142                 sessionPacket->getCvoExtMap(mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1),
143                                             &cvoExtMap);
144                 break;
145             }
146             case 3: {
147                 int64_t durationUs = mFdp.ConsumeIntegral<int64_t>();
148                 sessionPacket->getDurationUs(&durationUs);
149                 break;
150             }
151             case 4: {
152                 int32_t timeScale, numChannels;
153                 if (desc != nullptr) {
154                     sessionPacket->ParseFormatDesc(desc.c_str(), &timeScale, &numChannels);
155                 }
156                 break;
157             }
158             case 5: {
159                 if (checkFormatSupport(codec, format)) {
160                     sp<APacketSource> packetSource = sp<APacketSource>::make(
161                             sessionPacket, mFdp.ConsumeIntegralInRange(kMinIndex, trackSize - 1));
162                 }
163                 break;
164             }
165         }
166     }
167 }
168 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)169 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
170     ASessionPacketFuzzer packetSourceFuzzer(data, size);
171     packetSourceFuzzer.process();
172     return 0;
173 }
174