xref: /aosp_15_r20/frameworks/av/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 
17 #include <binder/Parcel.h>
18 #include <timedtext/TextDescriptions.h>
19 #include <timedtext_fuzz.pb.h>
20 #include "fuzzer/FuzzedDataProvider.h"
21 #include "src/libfuzzer/libfuzzer_macro.h"
22 
23 using namespace android;
24 constexpr int32_t kTextBytes = 2;
25 constexpr int32_t kChunkBytes = 8;
26 constexpr int32_t kChunkTypeBytes = 4;
27 constexpr int32_t kGlobalTextOffset = 0;
28 constexpr size_t kByte3Mask = 0xff000000UL;
29 constexpr size_t kByte2Mask = 0x00ff0000UL;
30 constexpr size_t kByte1Mask = 0x0000ff00UL;
31 constexpr size_t kByte0Mask = 0x000000ffUL;
32 
33 /**
34  * Sets ChunkSize/ChunkType (uint32_t) in timedtext-description vector<uint8_t>
35  * by extracting each byte from ChunkSize and populating the vector.
36  */
setChunkParameter(std::vector<uint8_t> & timedtext,size_t param,size_t paramOffset)37 void setChunkParameter(std::vector<uint8_t>& timedtext, size_t param, size_t paramOffset) {
38     timedtext[paramOffset + 0] = (param & kByte3Mask) >> 24;
39     timedtext[paramOffset + 1] = (param & kByte2Mask) >> 16;
40     timedtext[paramOffset + 2] = (param & kByte1Mask) >> 8;
41     timedtext[paramOffset + 3] = (param & kByte0Mask);
42 }
43 
44 /**
45  * Sets TextLength(uint16_t) in 3GPPLocal-description vector<uint8_t>
46  * by extracting each byte from TextLength and populating the vector.
47  */
setTextSize(std::vector<uint8_t> & local3GPPDescription,int32_t textLength)48 void setTextSize(std::vector<uint8_t>& local3GPPDescription, int32_t textLength) {
49     local3GPPDescription[0] = (textLength & kByte1Mask) >> 8;
50     local3GPPDescription[1] = (textLength & kByte0Mask);
51 }
52 
DEFINE_PROTO_FUZZER(const TimedText & input)53 DEFINE_PROTO_FUZZER(const TimedText& input) {
54     switch (input.handle()) {
55         case flag3gppglobal: {
56             size_t gppGlobalByteSize = input.global().ByteSizeLong();
57             if (gppGlobalByteSize) {
58                 std::vector<uint8_t> global3GPPDescription(gppGlobalByteSize + kChunkBytes);
59                 setChunkParameter(global3GPPDescription, gppGlobalByteSize, kGlobalTextOffset);
60                 setChunkParameter(global3GPPDescription, tx3g, kGlobalTextOffset + kChunkTypeBytes);
61                 input.global().SerializeToArray(global3GPPDescription.data() + kChunkBytes,
62                                                 global3GPPDescription.size());
63                 Parcel* parcel = new Parcel();
64                 TextDescriptions::getParcelOfDescriptions(
65                         global3GPPDescription.data(), global3GPPDescription.size(),
66                         TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::GLOBAL_DESCRIPTIONS,
67                         input.timems(), parcel);
68                 delete parcel;
69             }
70             break;
71         }
72         case flag3gpplocal: {
73             size_t gppLocalByteSize = input.local().ByteSizeLong();
74             if (gppLocalByteSize) {
75                 std::vector<uint8_t> local3GPPDescription(gppLocalByteSize + kChunkBytes +
76                                                           kTextBytes);
77                 std::string text = input.local().localtext().text();
78                 int32_t textLength = text.size();
79                 setTextSize(local3GPPDescription, textLength);
80                 input.local().localtext().SerializeToArray(local3GPPDescription.data() + kTextBytes,
81                                                            textLength);
82                 size_t gppLocalFormatSize = input.local().format().ByteSizeLong();
83                 size_t textOffset = textLength + kTextBytes;
84                 setChunkParameter(local3GPPDescription, gppLocalFormatSize, textOffset);
85                 switch (input.local().format().formatStyle_case()) {
86                     case GPPLocalFormat::FormatStyleCase::kTextbox: {
87                         setChunkParameter(local3GPPDescription, styl, textOffset + kChunkTypeBytes);
88                         input.local().format().SerializeToArray(
89                                 local3GPPDescription.data() + textOffset + kChunkBytes,
90                                 gppLocalFormatSize);
91                         break;
92                     }
93                     case GPPLocalFormat::FormatStyleCase::kHltbox: {
94                         setChunkParameter(local3GPPDescription, hlit, textOffset + kChunkTypeBytes);
95                         input.local().format().SerializeToArray(
96                                 local3GPPDescription.data() + textOffset + kChunkBytes,
97                                 gppLocalFormatSize);
98                         break;
99                     }
100                     case GPPLocalFormat::FormatStyleCase::kHltcolor: {
101                         setChunkParameter(local3GPPDescription, hclr, textOffset + kChunkTypeBytes);
102                         input.local().format().SerializeToArray(
103                                 local3GPPDescription.data() + textOffset + kChunkBytes,
104                                 gppLocalFormatSize);
105                         break;
106                     }
107                     case GPPLocalFormat::FormatStyleCase::kKrokbox: {
108                         setChunkParameter(local3GPPDescription, krok, textOffset + kChunkTypeBytes);
109                         input.local().format().SerializeToArray(
110                                 local3GPPDescription.data() + textOffset + kChunkBytes,
111                                 gppLocalFormatSize);
112                         break;
113                     }
114                     case GPPLocalFormat::FormatStyleCase::kScrollDelay: {
115                         setChunkParameter(local3GPPDescription, dlay, textOffset + kChunkTypeBytes);
116                         input.local().format().SerializeToArray(
117                                 local3GPPDescription.data() + textOffset + kChunkBytes,
118                                 gppLocalFormatSize);
119                         break;
120                     }
121                     case GPPLocalFormat::FormatStyleCase::kHrefBox: {
122                         setChunkParameter(local3GPPDescription, href, textOffset + kChunkTypeBytes);
123                         input.local().format().SerializeToArray(
124                                 local3GPPDescription.data() + textOffset + kChunkBytes,
125                                 gppLocalFormatSize);
126                         break;
127                     }
128                     case GPPLocalFormat::FormatStyleCase::kBoxrecord: {
129                         setChunkParameter(local3GPPDescription, tbox, textOffset + kChunkTypeBytes);
130                         input.local().format().SerializeToArray(
131                                 local3GPPDescription.data() + textOffset + kChunkBytes,
132                                 gppLocalFormatSize);
133                         break;
134                     }
135                     case GPPLocalFormat::FormatStyleCase::kBlinkBox: {
136                         setChunkParameter(local3GPPDescription, blnk, textOffset + kChunkTypeBytes);
137                         input.local().format().SerializeToArray(
138                                 local3GPPDescription.data() + textOffset + kChunkBytes,
139                                 gppLocalFormatSize);
140                         break;
141                     }
142                     case GPPLocalFormat::FormatStyleCase::kWrapFlag: {
143                         setChunkParameter(local3GPPDescription, txrp, textOffset + kChunkTypeBytes);
144                         input.local().format().SerializeToArray(
145                                 local3GPPDescription.data() + textOffset + kChunkBytes,
146                                 gppLocalFormatSize);
147                         break;
148                     }
149                     default: {
150                         break;
151                     }
152                 }
153                 Parcel* parcel = new Parcel();
154                 TextDescriptions::getParcelOfDescriptions(
155                         local3GPPDescription.data(), local3GPPDescription.size(),
156                         TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::LOCAL_DESCRIPTIONS,
157                         input.timems(), parcel);
158                 delete parcel;
159             }
160             break;
161         }
162         case flagsrtlocal: {
163             size_t srtByteSize = input.srt().ByteSizeLong();
164             if (srtByteSize) {
165                 std::vector<uint8_t> srtLocalDescription(srtByteSize);
166                 input.srt().SerializeToArray(srtLocalDescription.data(),
167                                              srtLocalDescription.size());
168                 Parcel* parcel = new Parcel();
169                 TextDescriptions::getParcelOfDescriptions(
170                         srtLocalDescription.data(), srtLocalDescription.size(),
171                         TextDescriptions::OUT_OF_BAND_TEXT_SRT |
172                                 TextDescriptions::LOCAL_DESCRIPTIONS,
173                         input.timems(), parcel);
174                 delete parcel;
175             }
176             break;
177         }
178         default:
179             break;
180     }
181 }
182