1 /*
2 * Copyright (C) 2021 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 "perfetto/ext/base/base64.h"
18
19 #include "perfetto/ext/base/string_view.h"
20 #include "perfetto/ext/base/utils.h"
21 #include "test/gtest_and_gmock.h"
22
23 namespace perfetto {
24 namespace base {
25 namespace {
26
27 struct TestPattern {
28 size_t decoded_len;
29 const char* decoded;
30 const char* encoded;
31 };
32
33 TestPattern kPatterns[] = {
34
35 // Basic bit patterns;
36 // values obtained with "echo -n '...' | uuencode -m test"
37
38 {1, "\000", "AA=="},
39 {1, "\001", "AQ=="},
40 {1, "\002", "Ag=="},
41 {1, "\004", "BA=="},
42 {1, "\010", "CA=="},
43 {1, "\020", "EA=="},
44 {1, "\040", "IA=="},
45 {1, "\100", "QA=="},
46 {1, "\200", "gA=="},
47
48 {1, "\377", "/w=="},
49 {1, "\376", "/g=="},
50 {1, "\375", "/Q=="},
51 {1, "\373", "+w=="},
52 {1, "\367", "9w=="},
53 {1, "\357", "7w=="},
54 {1, "\337", "3w=="},
55 {1, "\277", "vw=="},
56 {1, "\177", "fw=="},
57 {2, "\000\000", "AAA="},
58 {2, "\000\001", "AAE="},
59 {2, "\000\002", "AAI="},
60 {2, "\000\004", "AAQ="},
61 {2, "\000\010", "AAg="},
62 {2, "\000\020", "ABA="},
63 {2, "\000\040", "ACA="},
64 {2, "\000\100", "AEA="},
65 {2, "\000\200", "AIA="},
66 {2, "\001\000", "AQA="},
67 {2, "\002\000", "AgA="},
68 {2, "\004\000", "BAA="},
69 {2, "\010\000", "CAA="},
70 {2, "\020\000", "EAA="},
71 {2, "\040\000", "IAA="},
72 {2, "\100\000", "QAA="},
73 {2, "\200\000", "gAA="},
74
75 {2, "\377\377", "//8="},
76 {2, "\377\376", "//4="},
77 {2, "\377\375", "//0="},
78 {2, "\377\373", "//s="},
79 {2, "\377\367", "//c="},
80 {2, "\377\357", "/+8="},
81 {2, "\377\337", "/98="},
82 {2, "\377\277", "/78="},
83 {2, "\377\177", "/38="},
84 {2, "\376\377", "/v8="},
85 {2, "\375\377", "/f8="},
86 {2, "\373\377", "+/8="},
87 {2, "\367\377", "9/8="},
88 {2, "\357\377", "7/8="},
89 {2, "\337\377", "3/8="},
90 {2, "\277\377", "v/8="},
91 {2, "\177\377", "f/8="},
92
93 {3, "\000\000\000", "AAAA"},
94 {3, "\000\000\001", "AAAB"},
95 {3, "\000\000\002", "AAAC"},
96 {3, "\000\000\004", "AAAE"},
97 {3, "\000\000\010", "AAAI"},
98 {3, "\000\000\020", "AAAQ"},
99 {3, "\000\000\040", "AAAg"},
100 {3, "\000\000\100", "AABA"},
101 {3, "\000\000\200", "AACA"},
102 {3, "\000\001\000", "AAEA"},
103 {3, "\000\002\000", "AAIA"},
104 {3, "\000\004\000", "AAQA"},
105 {3, "\000\010\000", "AAgA"},
106 {3, "\000\020\000", "ABAA"},
107 {3, "\000\040\000", "ACAA"},
108 {3, "\000\100\000", "AEAA"},
109 {3, "\000\200\000", "AIAA"},
110 {3, "\001\000\000", "AQAA"},
111 {3, "\002\000\000", "AgAA"},
112 {3, "\004\000\000", "BAAA"},
113 {3, "\010\000\000", "CAAA"},
114 {3, "\020\000\000", "EAAA"},
115 {3, "\040\000\000", "IAAA"},
116 {3, "\100\000\000", "QAAA"},
117 {3, "\200\000\000", "gAAA"},
118
119 {3, "\377\377\377", "////"},
120 {3, "\377\377\376", "///+"},
121 {3, "\377\377\375", "///9"},
122 {3, "\377\377\373", "///7"},
123 {3, "\377\377\367", "///3"},
124 {3, "\377\377\357", "///v"},
125 {3, "\377\377\337", "///f"},
126 {3, "\377\377\277", "//+/"},
127 {3, "\377\377\177", "//9/"},
128 {3, "\377\376\377", "//7/"},
129 {3, "\377\375\377", "//3/"},
130 {3, "\377\373\377", "//v/"},
131 {3, "\377\367\377", "//f/"},
132 {3, "\377\357\377", "/+//"},
133 {3, "\377\337\377", "/9//"},
134 {3, "\377\277\377", "/7//"},
135 {3, "\377\177\377", "/3//"},
136 {3, "\376\377\377", "/v//"},
137 {3, "\375\377\377", "/f//"},
138 {3, "\373\377\377", "+///"},
139 {3, "\367\377\377", "9///"},
140 {3, "\357\377\377", "7///"},
141 {3, "\337\377\377", "3///"},
142 {3, "\277\377\377", "v///"},
143 {3, "\177\377\377", "f///"},
144
145 // Random numbers: values obtained with
146 //
147 // #! /bin/bash
148 // dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random
149 // od -N $1 -t o1 /tmp/bar.random
150 // uuencode -m test < /tmp/bar.random
151 //
152 // where $1 is the number of bytes (2, 3)
153
154 {2, "\243\361", "o/E="},
155 {2, "\024\167", "FHc="},
156 {2, "\313\252", "y6o="},
157 {2, "\046\041", "JiE="},
158 {2, "\145\236", "ZZ4="},
159 {2, "\254\325", "rNU="},
160 {2, "\061\330", "Mdg="},
161 {2, "\245\032", "pRo="},
162 {2, "\006\000", "BgA="},
163 {2, "\375\131", "/Vk="},
164 {2, "\303\210", "w4g="},
165 {2, "\040\037", "IB8="},
166 {2, "\261\372", "sfo="},
167 {2, "\335\014", "3Qw="},
168 {2, "\233\217", "m48="},
169 {2, "\373\056", "+y4="},
170 {2, "\247\232", "p5o="},
171 {2, "\107\053", "Rys="},
172 {2, "\204\077", "hD8="},
173 {2, "\276\211", "vok="},
174 {2, "\313\110", "y0g="},
175 {2, "\363\376", "8/4="},
176 {2, "\251\234", "qZw="},
177 {2, "\103\262", "Q7I="},
178 {2, "\142\312", "Yso="},
179 {2, "\067\211", "N4k="},
180 {2, "\220\001", "kAE="},
181 {2, "\152\240", "aqA="},
182 {2, "\367\061", "9zE="},
183 {2, "\133\255", "W60="},
184 {2, "\176\035", "fh0="},
185 {2, "\032\231", "Gpk="},
186
187 {3, "\013\007\144", "Cwdk"},
188 {3, "\030\112\106", "GEpG"},
189 {3, "\047\325\046", "J9Um"},
190 {3, "\310\160\022", "yHAS"},
191 {3, "\131\100\237", "WUCf"},
192 {3, "\064\342\134", "NOJc"},
193 {3, "\010\177\004", "CH8E"},
194 {3, "\345\147\205", "5WeF"},
195 {3, "\300\343\360", "wOPw"},
196 {3, "\061\240\201", "MaCB"},
197 {3, "\225\333\044", "ldsk"},
198 {3, "\215\137\352", "jV/q"},
199 {3, "\371\147\160", "+Wdw"},
200 {3, "\030\320\051", "GNAp"},
201 {3, "\044\174\241", "JHyh"},
202 {3, "\260\127\037", "sFcf"},
203 {3, "\111\045\033", "SSUb"},
204 {3, "\202\114\107", "gkxH"},
205 {3, "\057\371\042", "L/ki"},
206 {3, "\223\247\244", "k6ek"},
207 {3, "\047\216\144", "J45k"},
208 {3, "\203\070\327", "gzjX"},
209 {3, "\247\140\072", "p2A6"},
210 {3, "\124\115\116", "VE1O"},
211 {3, "\157\162\050", "b3Io"},
212 {3, "\357\223\004", "75ME"},
213 {3, "\052\117\156", "Kk9u"},
214 {3, "\347\154\000", "52wA"},
215 {3, "\303\012\142", "wwpi"},
216 {3, "\060\035\362", "MB3y"},
217 {3, "\130\226\361", "WJbx"},
218 {3, "\173\013\071", "ews5"},
219 {3, "\336\004\027", "3gQX"},
220 {3, "\357\366\234", "7/ac"},
221 {3, "\353\304\111", "68RJ"},
222 {3, "\024\264\131", "FLRZ"},
223 {3, "\075\114\251", "PUyp"},
224 {3, "\315\031\225", "zRmV"},
225 {3, "\154\201\276", "bIG+"},
226 {3, "\200\066\072", "gDY6"},
227 {3, "\142\350\267", "Yui3"},
228 {3, "\033\000\166", "GwB2"},
229 {3, "\210\055\077", "iC0/"},
230 {3, "\341\037\124", "4R9U"},
231 {3, "\161\103\152", "cUNq"},
232 {3, "\270\142\131", "uGJZ"},
233 {3, "\337\076\074", "3z48"},
234 {3, "\375\106\362", "/Uby"},
235 {3, "\227\301\127", "l8FX"},
236 {3, "\340\002\234", "4AKc"},
237 {3, "\121\064\033", "UTQb"},
238 {3, "\157\134\143", "b1xj"},
239 {3, "\247\055\327", "py3X"},
240 {3, "\340\142\005", "4GIF"},
241 {3, "\060\260\143", "MLBj"},
242 {3, "\075\203\170", "PYN4"},
243 {3, "\143\160\016", "Y3AO"},
244 {3, "\313\013\063", "ywsz"},
245 {3, "\174\236\135", "fJ5d"},
246 {3, "\103\047\026", "QycW"},
247 {3, "\365\005\343", "9QXj"},
248 {3, "\271\160\223", "uXCT"},
249 {3, "\362\255\172", "8q16"},
250 {3, "\113\012\015", "SwoN"},
251
252 // various lengths, generated by this python script:
253 //
254 // from string import lowercase as lc
255 // for i in range(27):
256 // print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i),
257 // lc[:i].encode('base64').strip())
258
259 {0, "abcdefghijklmnopqrstuvwxyz", ""},
260 {1, "abcdefghijklmnopqrstuvwxyz", "YQ=="},
261 {2, "abcdefghijklmnopqrstuvwxyz", "YWI="},
262 {3, "abcdefghijklmnopqrstuvwxyz", "YWJj"},
263 {4, "abcdefghijklmnopqrstuvwxyz", "YWJjZA=="},
264 {5, "abcdefghijklmnopqrstuvwxyz", "YWJjZGU="},
265 {6, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVm"},
266 {7, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZw=="},
267 {8, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2g="},
268 {9, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hp"},
269 {10, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpag=="},
270 {11, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpams="},
271 {12, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamts"},
272 {13, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbQ=="},
273 {14, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW4="},
274 {15, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5v"},
275 {16, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcA=="},
276 {17, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHE="},
277 {18, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFy"},
278 {19, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFycw=="},
279 {20, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q="},
280 {21, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1"},
281 {22, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg=="},
282 {23, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc="},
283 {24, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4"},
284 {25, "abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ=="},
285 {26, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="},
286 };
287
TEST(Base64Test,Encode)288 TEST(Base64Test, Encode) {
289 EXPECT_EQ(Base64Encode(""), "");
290 EXPECT_EQ(Base64Encode("f"), "Zg==");
291 EXPECT_EQ(Base64Encode("fo"), "Zm8=");
292 EXPECT_EQ(Base64Encode("foo"), "Zm9v");
293 EXPECT_EQ(Base64Encode("foob"), "Zm9vYg==");
294 EXPECT_EQ(Base64Encode("fooba"), "Zm9vYmE=");
295 EXPECT_EQ(Base64Encode("foobar"), "Zm9vYmFy");
296 EXPECT_EQ(Base64Encode("\xff"), "/w==");
297 EXPECT_EQ(Base64Encode("\xff\xfe"), "//4=");
298 EXPECT_EQ(Base64Encode("\xff\xfe\xfd"), "//79");
299 EXPECT_EQ(Base64Encode("\xff\xfe\xfd\xfc"), "//79/A==");
300
301 for (size_t i = 0; i < ArraySize(kPatterns); ++i) {
302 const auto& p = kPatterns[i];
303 std::string res = Base64Encode(StringView(p.decoded, p.decoded_len));
304 EXPECT_EQ(p.encoded, res);
305 }
306
307 // Error cases
308 char buf[4];
309 EXPECT_EQ(0, Base64Encode("", 0, buf, 0));
310 EXPECT_EQ(0, Base64Encode("", 0, buf, 1));
311 EXPECT_EQ(-1, Base64Encode("a", 1, buf, 0));
312 EXPECT_EQ(-1, Base64Encode("abc", 3, buf, 0));
313 EXPECT_EQ(-1, Base64Encode("abc", 3, buf, 1));
314 EXPECT_EQ(-1, Base64Encode("abc", 3, buf, 3));
315 EXPECT_EQ(4, Base64Encode("abc", 3, buf, 4));
316 }
317
TEST(Base64Test,Decode)318 TEST(Base64Test, Decode) {
319 EXPECT_EQ(Base64Decode(""), "");
320 EXPECT_EQ(Base64Decode("Zg=="), "f");
321 EXPECT_EQ(Base64Decode("Zg="), "f");
322 EXPECT_EQ(Base64Decode("Zg"), "f");
323 EXPECT_EQ(Base64Decode("Zm8="), "fo");
324 EXPECT_EQ(Base64Decode("Zm8"), "fo");
325 EXPECT_EQ(Base64Decode("Zm9v"), "foo");
326 EXPECT_EQ(Base64Decode("Zm9vYg=="), "foob");
327 EXPECT_EQ(Base64Decode("Zm9vYg="), "foob");
328 EXPECT_EQ(Base64Decode("Zm9vYg"), "foob");
329 EXPECT_EQ(Base64Decode("Zm9vYmE="), "fooba");
330 EXPECT_EQ(Base64Decode("Zm9vYmE"), "fooba");
331 EXPECT_EQ(Base64Decode("Zm9vYmFy"), "foobar");
332 EXPECT_EQ(Base64Decode("/w=="), "\xff");
333 EXPECT_EQ(Base64Decode("/w="), "\xff");
334 EXPECT_EQ(Base64Decode("/w"), "\xff");
335 EXPECT_EQ(Base64Decode("//4="), "\xff\xfe");
336 EXPECT_EQ(Base64Decode("//4"), "\xff\xfe");
337 EXPECT_EQ(Base64Decode("//79"), "\xff\xfe\xfd");
338 EXPECT_EQ(Base64Decode("//79/A=="), "\xff\xfe\xfd\xfc");
339 EXPECT_EQ(Base64Decode("//79/A="), "\xff\xfe\xfd\xfc");
340 EXPECT_EQ(Base64Decode("//79/A"), "\xff\xfe\xfd\xfc");
341
342 for (size_t i = 0; i < ArraySize(kPatterns); ++i) {
343 const auto& p = kPatterns[i];
344 std::optional<std::string> dec = Base64Decode(StringView(p.encoded));
345 EXPECT_TRUE(dec.has_value());
346 EXPECT_EQ(dec.value(), StringView(p.decoded, p.decoded_len).ToStdString());
347 }
348
349 // Error cases:
350 EXPECT_EQ(Base64Decode("Z"), std::nullopt);
351 EXPECT_EQ(Base64Decode("Zm9vY"), std::nullopt);
352
353 uint8_t buf[4];
354 EXPECT_EQ(Base64Decode("", 0, buf, 2), 0); // Valid, 0 len.
355 EXPECT_EQ(Base64Decode("Z", 1, buf, 1), -1); // Invalid input.
356 EXPECT_EQ(Base64Decode("Zg==", 4, buf, 1), -1); // Not enough dst space.
357 }
358
359 } // namespace
360 } // namespace base
361 } // namespace perfetto
362