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