Austin Schuh | 36244a1 | 2019-09-21 17:52:38 -0700 | [diff] [blame^] | 1 | // Copyright 2017 The Abseil Authors. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include "absl/strings/escaping.h" |
| 16 | |
| 17 | #include <array> |
| 18 | #include <cstdio> |
| 19 | #include <cstring> |
| 20 | #include <memory> |
| 21 | #include <vector> |
| 22 | |
| 23 | #include "gmock/gmock.h" |
| 24 | #include "gtest/gtest.h" |
| 25 | #include "absl/container/fixed_array.h" |
| 26 | #include "absl/strings/str_cat.h" |
| 27 | |
| 28 | #include "absl/strings/internal/escaping_test_common.h" |
| 29 | |
| 30 | namespace { |
| 31 | |
| 32 | struct epair { |
| 33 | std::string escaped; |
| 34 | std::string unescaped; |
| 35 | }; |
| 36 | |
| 37 | TEST(CEscape, EscapeAndUnescape) { |
| 38 | const std::string inputs[] = { |
| 39 | std::string("foo\nxx\r\b\0023"), |
| 40 | std::string(""), |
| 41 | std::string("abc"), |
| 42 | std::string("\1chad_rules"), |
| 43 | std::string("\1arnar_drools"), |
| 44 | std::string("xxxx\r\t'\"\\"), |
| 45 | std::string("\0xx\0", 4), |
| 46 | std::string("\x01\x31"), |
| 47 | std::string("abc\xb\x42\141bc"), |
| 48 | std::string("123\1\x31\x32\x33"), |
| 49 | std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"), |
| 50 | std::string( |
| 51 | "\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"), |
| 52 | }; |
| 53 | // Do this twice, once for octal escapes and once for hex escapes. |
| 54 | for (int kind = 0; kind < 4; kind++) { |
| 55 | for (const std::string& original : inputs) { |
| 56 | std::string escaped; |
| 57 | switch (kind) { |
| 58 | case 0: |
| 59 | escaped = absl::CEscape(original); |
| 60 | break; |
| 61 | case 1: |
| 62 | escaped = absl::CHexEscape(original); |
| 63 | break; |
| 64 | case 2: |
| 65 | escaped = absl::Utf8SafeCEscape(original); |
| 66 | break; |
| 67 | case 3: |
| 68 | escaped = absl::Utf8SafeCHexEscape(original); |
| 69 | break; |
| 70 | } |
| 71 | std::string unescaped_str; |
| 72 | EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str)); |
| 73 | EXPECT_EQ(unescaped_str, original); |
| 74 | |
| 75 | unescaped_str.erase(); |
| 76 | std::string error; |
| 77 | EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str, &error)); |
| 78 | EXPECT_EQ(error, ""); |
| 79 | |
| 80 | // Check in-place unescaping |
| 81 | std::string s = escaped; |
| 82 | EXPECT_TRUE(absl::CUnescape(s, &s)); |
| 83 | ASSERT_EQ(s, original); |
| 84 | } |
| 85 | } |
| 86 | // Check that all possible two character strings can be escaped then |
| 87 | // unescaped successfully. |
| 88 | for (int char0 = 0; char0 < 256; char0++) { |
| 89 | for (int char1 = 0; char1 < 256; char1++) { |
| 90 | char chars[2]; |
| 91 | chars[0] = char0; |
| 92 | chars[1] = char1; |
| 93 | std::string s(chars, 2); |
| 94 | std::string escaped = absl::CHexEscape(s); |
| 95 | std::string unescaped; |
| 96 | EXPECT_TRUE(absl::CUnescape(escaped, &unescaped)); |
| 97 | EXPECT_EQ(s, unescaped); |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | TEST(CEscape, BasicEscaping) { |
| 103 | epair oct_values[] = { |
| 104 | {"foo\\rbar\\nbaz\\t", "foo\rbar\nbaz\t"}, |
| 105 | {"\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", |
| 106 | "'full of \"sound\" and \"fury\"'"}, |
| 107 | {"signi\\\\fying\\\\ nothing\\\\", "signi\\fying\\ nothing\\"}, |
| 108 | {"\\010\\t\\n\\013\\014\\r", "\010\011\012\013\014\015"} |
| 109 | }; |
| 110 | epair hex_values[] = { |
| 111 | {"ubik\\rubik\\nubik\\t", "ubik\rubik\nubik\t"}, |
| 112 | {"I\\\'ve just seen a \\\"face\\\"", |
| 113 | "I've just seen a \"face\""}, |
| 114 | {"hel\\\\ter\\\\skel\\\\ter\\\\", "hel\\ter\\skel\\ter\\"}, |
| 115 | {"\\x08\\t\\n\\x0b\\x0c\\r", "\010\011\012\013\014\015"} |
| 116 | }; |
| 117 | epair utf8_oct_values[] = { |
| 118 | {"\xe8\xb0\xb7\xe6\xad\x8c\\r\xe8\xb0\xb7\xe6\xad\x8c\\nbaz\\t", |
| 119 | "\xe8\xb0\xb7\xe6\xad\x8c\r\xe8\xb0\xb7\xe6\xad\x8c\nbaz\t"}, |
| 120 | {"\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name", |
| 121 | "\"\xe8\xb0\xb7\xe6\xad\x8c\" is Google\'s Chinese name"}, |
| 122 | {"\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\xab\\\\are\\\\Japanese\\\\chars\\\\", |
| 123 | "\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\xab\\are\\Japanese\\chars\\"}, |
| 124 | {"\xed\x81\xac\xeb\xa1\xac\\010\\t\\n\\013\\014\\r", |
| 125 | "\xed\x81\xac\xeb\xa1\xac\010\011\012\013\014\015"} |
| 126 | }; |
| 127 | epair utf8_hex_values[] = { |
| 128 | {"\x20\xe4\xbd\xa0\\t\xe5\xa5\xbd,\\r!\\n", |
| 129 | "\x20\xe4\xbd\xa0\t\xe5\xa5\xbd,\r!\n"}, |
| 130 | {"\xe8\xa9\xa6\xe9\xa8\x93\\\' means \\\"test\\\"", |
| 131 | "\xe8\xa9\xa6\xe9\xa8\x93\' means \"test\""}, |
| 132 | {"\\\\\xe6\x88\x91\\\\:\\\\\xe6\x9d\xa8\xe6\xac\xa2\\\\", |
| 133 | "\\\xe6\x88\x91\\:\\\xe6\x9d\xa8\xe6\xac\xa2\\"}, |
| 134 | {"\xed\x81\xac\xeb\xa1\xac\\x08\\t\\n\\x0b\\x0c\\r", |
| 135 | "\xed\x81\xac\xeb\xa1\xac\010\011\012\013\014\015"} |
| 136 | }; |
| 137 | |
| 138 | for (const epair& val : oct_values) { |
| 139 | std::string escaped = absl::CEscape(val.unescaped); |
| 140 | EXPECT_EQ(escaped, val.escaped); |
| 141 | } |
| 142 | for (const epair& val : hex_values) { |
| 143 | std::string escaped = absl::CHexEscape(val.unescaped); |
| 144 | EXPECT_EQ(escaped, val.escaped); |
| 145 | } |
| 146 | for (const epair& val : utf8_oct_values) { |
| 147 | std::string escaped = absl::Utf8SafeCEscape(val.unescaped); |
| 148 | EXPECT_EQ(escaped, val.escaped); |
| 149 | } |
| 150 | for (const epair& val : utf8_hex_values) { |
| 151 | std::string escaped = absl::Utf8SafeCHexEscape(val.unescaped); |
| 152 | EXPECT_EQ(escaped, val.escaped); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | TEST(Unescape, BasicFunction) { |
| 157 | epair tests[] = |
| 158 | {{"", ""}, |
| 159 | {"\\u0030", "0"}, |
| 160 | {"\\u00A3", "\xC2\xA3"}, |
| 161 | {"\\u22FD", "\xE2\x8B\xBD"}, |
| 162 | {"\\U00010000", "\xF0\x90\x80\x80"}, |
| 163 | {"\\U0010FFFD", "\xF4\x8F\xBF\xBD"}}; |
| 164 | for (const epair& val : tests) { |
| 165 | std::string out; |
| 166 | EXPECT_TRUE(absl::CUnescape(val.escaped, &out)); |
| 167 | EXPECT_EQ(out, val.unescaped); |
| 168 | } |
| 169 | std::string bad[] = {"\\u1", // too short |
| 170 | "\\U1", // too short |
| 171 | "\\Uffffff", // exceeds 0x10ffff (largest Unicode) |
| 172 | "\\U00110000", // exceeds 0x10ffff (largest Unicode) |
| 173 | "\\uD835", // surrogate character (D800-DFFF) |
| 174 | "\\U0000DD04", // surrogate character (D800-DFFF) |
| 175 | "\\777", // exceeds 0xff |
| 176 | "\\xABCD"}; // exceeds 0xff |
| 177 | for (const std::string& e : bad) { |
| 178 | std::string error; |
| 179 | std::string out; |
| 180 | EXPECT_FALSE(absl::CUnescape(e, &out, &error)); |
| 181 | EXPECT_FALSE(error.empty()); |
| 182 | |
| 183 | out.erase(); |
| 184 | EXPECT_FALSE(absl::CUnescape(e, &out)); |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | class CUnescapeTest : public testing::Test { |
| 189 | protected: |
| 190 | static const char kStringWithMultipleOctalNulls[]; |
| 191 | static const char kStringWithMultipleHexNulls[]; |
| 192 | static const char kStringWithMultipleUnicodeNulls[]; |
| 193 | |
| 194 | std::string result_string_; |
| 195 | }; |
| 196 | |
| 197 | const char CUnescapeTest::kStringWithMultipleOctalNulls[] = |
| 198 | "\\0\\n" // null escape \0 plus newline |
| 199 | "0\\n" // just a number 0 (not a null escape) plus newline |
| 200 | "\\00\\12" // null escape \00 plus octal newline code |
| 201 | "\\000"; // null escape \000 |
| 202 | |
| 203 | // This has the same ingredients as kStringWithMultipleOctalNulls |
| 204 | // but with \x hex escapes instead of octal escapes. |
| 205 | const char CUnescapeTest::kStringWithMultipleHexNulls[] = |
| 206 | "\\x0\\n" |
| 207 | "0\\n" |
| 208 | "\\x00\\xa" |
| 209 | "\\x000"; |
| 210 | |
| 211 | const char CUnescapeTest::kStringWithMultipleUnicodeNulls[] = |
| 212 | "\\u0000\\n" // short-form (4-digit) null escape plus newline |
| 213 | "0\\n" // just a number 0 (not a null escape) plus newline |
| 214 | "\\U00000000"; // long-form (8-digit) null escape |
| 215 | |
| 216 | TEST_F(CUnescapeTest, Unescapes1CharOctalNull) { |
| 217 | std::string original_string = "\\0"; |
| 218 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 219 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 220 | } |
| 221 | |
| 222 | TEST_F(CUnescapeTest, Unescapes2CharOctalNull) { |
| 223 | std::string original_string = "\\00"; |
| 224 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 225 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 226 | } |
| 227 | |
| 228 | TEST_F(CUnescapeTest, Unescapes3CharOctalNull) { |
| 229 | std::string original_string = "\\000"; |
| 230 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 231 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 232 | } |
| 233 | |
| 234 | TEST_F(CUnescapeTest, Unescapes1CharHexNull) { |
| 235 | std::string original_string = "\\x0"; |
| 236 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 237 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 238 | } |
| 239 | |
| 240 | TEST_F(CUnescapeTest, Unescapes2CharHexNull) { |
| 241 | std::string original_string = "\\x00"; |
| 242 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 243 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 244 | } |
| 245 | |
| 246 | TEST_F(CUnescapeTest, Unescapes3CharHexNull) { |
| 247 | std::string original_string = "\\x000"; |
| 248 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 249 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 250 | } |
| 251 | |
| 252 | TEST_F(CUnescapeTest, Unescapes4CharUnicodeNull) { |
| 253 | std::string original_string = "\\u0000"; |
| 254 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 255 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 256 | } |
| 257 | |
| 258 | TEST_F(CUnescapeTest, Unescapes8CharUnicodeNull) { |
| 259 | std::string original_string = "\\U00000000"; |
| 260 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 261 | EXPECT_EQ(std::string("\0", 1), result_string_); |
| 262 | } |
| 263 | |
| 264 | TEST_F(CUnescapeTest, UnescapesMultipleOctalNulls) { |
| 265 | std::string original_string(kStringWithMultipleOctalNulls); |
| 266 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 267 | // All escapes, including newlines and null escapes, should have been |
| 268 | // converted to the equivalent characters. |
| 269 | EXPECT_EQ(std::string("\0\n" |
| 270 | "0\n" |
| 271 | "\0\n" |
| 272 | "\0", |
| 273 | 7), |
| 274 | result_string_); |
| 275 | } |
| 276 | |
| 277 | |
| 278 | TEST_F(CUnescapeTest, UnescapesMultipleHexNulls) { |
| 279 | std::string original_string(kStringWithMultipleHexNulls); |
| 280 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 281 | EXPECT_EQ(std::string("\0\n" |
| 282 | "0\n" |
| 283 | "\0\n" |
| 284 | "\0", |
| 285 | 7), |
| 286 | result_string_); |
| 287 | } |
| 288 | |
| 289 | TEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) { |
| 290 | std::string original_string(kStringWithMultipleUnicodeNulls); |
| 291 | EXPECT_TRUE(absl::CUnescape(original_string, &result_string_)); |
| 292 | EXPECT_EQ(std::string("\0\n" |
| 293 | "0\n" |
| 294 | "\0", |
| 295 | 5), |
| 296 | result_string_); |
| 297 | } |
| 298 | |
| 299 | static struct { |
| 300 | absl::string_view plaintext; |
| 301 | absl::string_view cyphertext; |
| 302 | } const base64_tests[] = { |
| 303 | // Empty std::string. |
| 304 | {{"", 0}, {"", 0}}, |
| 305 | {{nullptr, 0}, |
| 306 | {"", 0}}, // if length is zero, plaintext ptr must be ignored! |
| 307 | |
| 308 | // Basic bit patterns; |
| 309 | // values obtained with "echo -n '...' | uuencode -m test" |
| 310 | |
| 311 | {{"\000", 1}, "AA=="}, |
| 312 | {{"\001", 1}, "AQ=="}, |
| 313 | {{"\002", 1}, "Ag=="}, |
| 314 | {{"\004", 1}, "BA=="}, |
| 315 | {{"\010", 1}, "CA=="}, |
| 316 | {{"\020", 1}, "EA=="}, |
| 317 | {{"\040", 1}, "IA=="}, |
| 318 | {{"\100", 1}, "QA=="}, |
| 319 | {{"\200", 1}, "gA=="}, |
| 320 | |
| 321 | {{"\377", 1}, "/w=="}, |
| 322 | {{"\376", 1}, "/g=="}, |
| 323 | {{"\375", 1}, "/Q=="}, |
| 324 | {{"\373", 1}, "+w=="}, |
| 325 | {{"\367", 1}, "9w=="}, |
| 326 | {{"\357", 1}, "7w=="}, |
| 327 | {{"\337", 1}, "3w=="}, |
| 328 | {{"\277", 1}, "vw=="}, |
| 329 | {{"\177", 1}, "fw=="}, |
| 330 | {{"\000\000", 2}, "AAA="}, |
| 331 | {{"\000\001", 2}, "AAE="}, |
| 332 | {{"\000\002", 2}, "AAI="}, |
| 333 | {{"\000\004", 2}, "AAQ="}, |
| 334 | {{"\000\010", 2}, "AAg="}, |
| 335 | {{"\000\020", 2}, "ABA="}, |
| 336 | {{"\000\040", 2}, "ACA="}, |
| 337 | {{"\000\100", 2}, "AEA="}, |
| 338 | {{"\000\200", 2}, "AIA="}, |
| 339 | {{"\001\000", 2}, "AQA="}, |
| 340 | {{"\002\000", 2}, "AgA="}, |
| 341 | {{"\004\000", 2}, "BAA="}, |
| 342 | {{"\010\000", 2}, "CAA="}, |
| 343 | {{"\020\000", 2}, "EAA="}, |
| 344 | {{"\040\000", 2}, "IAA="}, |
| 345 | {{"\100\000", 2}, "QAA="}, |
| 346 | {{"\200\000", 2}, "gAA="}, |
| 347 | |
| 348 | {{"\377\377", 2}, "//8="}, |
| 349 | {{"\377\376", 2}, "//4="}, |
| 350 | {{"\377\375", 2}, "//0="}, |
| 351 | {{"\377\373", 2}, "//s="}, |
| 352 | {{"\377\367", 2}, "//c="}, |
| 353 | {{"\377\357", 2}, "/+8="}, |
| 354 | {{"\377\337", 2}, "/98="}, |
| 355 | {{"\377\277", 2}, "/78="}, |
| 356 | {{"\377\177", 2}, "/38="}, |
| 357 | {{"\376\377", 2}, "/v8="}, |
| 358 | {{"\375\377", 2}, "/f8="}, |
| 359 | {{"\373\377", 2}, "+/8="}, |
| 360 | {{"\367\377", 2}, "9/8="}, |
| 361 | {{"\357\377", 2}, "7/8="}, |
| 362 | {{"\337\377", 2}, "3/8="}, |
| 363 | {{"\277\377", 2}, "v/8="}, |
| 364 | {{"\177\377", 2}, "f/8="}, |
| 365 | |
| 366 | {{"\000\000\000", 3}, "AAAA"}, |
| 367 | {{"\000\000\001", 3}, "AAAB"}, |
| 368 | {{"\000\000\002", 3}, "AAAC"}, |
| 369 | {{"\000\000\004", 3}, "AAAE"}, |
| 370 | {{"\000\000\010", 3}, "AAAI"}, |
| 371 | {{"\000\000\020", 3}, "AAAQ"}, |
| 372 | {{"\000\000\040", 3}, "AAAg"}, |
| 373 | {{"\000\000\100", 3}, "AABA"}, |
| 374 | {{"\000\000\200", 3}, "AACA"}, |
| 375 | {{"\000\001\000", 3}, "AAEA"}, |
| 376 | {{"\000\002\000", 3}, "AAIA"}, |
| 377 | {{"\000\004\000", 3}, "AAQA"}, |
| 378 | {{"\000\010\000", 3}, "AAgA"}, |
| 379 | {{"\000\020\000", 3}, "ABAA"}, |
| 380 | {{"\000\040\000", 3}, "ACAA"}, |
| 381 | {{"\000\100\000", 3}, "AEAA"}, |
| 382 | {{"\000\200\000", 3}, "AIAA"}, |
| 383 | {{"\001\000\000", 3}, "AQAA"}, |
| 384 | {{"\002\000\000", 3}, "AgAA"}, |
| 385 | {{"\004\000\000", 3}, "BAAA"}, |
| 386 | {{"\010\000\000", 3}, "CAAA"}, |
| 387 | {{"\020\000\000", 3}, "EAAA"}, |
| 388 | {{"\040\000\000", 3}, "IAAA"}, |
| 389 | {{"\100\000\000", 3}, "QAAA"}, |
| 390 | {{"\200\000\000", 3}, "gAAA"}, |
| 391 | |
| 392 | {{"\377\377\377", 3}, "////"}, |
| 393 | {{"\377\377\376", 3}, "///+"}, |
| 394 | {{"\377\377\375", 3}, "///9"}, |
| 395 | {{"\377\377\373", 3}, "///7"}, |
| 396 | {{"\377\377\367", 3}, "///3"}, |
| 397 | {{"\377\377\357", 3}, "///v"}, |
| 398 | {{"\377\377\337", 3}, "///f"}, |
| 399 | {{"\377\377\277", 3}, "//+/"}, |
| 400 | {{"\377\377\177", 3}, "//9/"}, |
| 401 | {{"\377\376\377", 3}, "//7/"}, |
| 402 | {{"\377\375\377", 3}, "//3/"}, |
| 403 | {{"\377\373\377", 3}, "//v/"}, |
| 404 | {{"\377\367\377", 3}, "//f/"}, |
| 405 | {{"\377\357\377", 3}, "/+//"}, |
| 406 | {{"\377\337\377", 3}, "/9//"}, |
| 407 | {{"\377\277\377", 3}, "/7//"}, |
| 408 | {{"\377\177\377", 3}, "/3//"}, |
| 409 | {{"\376\377\377", 3}, "/v//"}, |
| 410 | {{"\375\377\377", 3}, "/f//"}, |
| 411 | {{"\373\377\377", 3}, "+///"}, |
| 412 | {{"\367\377\377", 3}, "9///"}, |
| 413 | {{"\357\377\377", 3}, "7///"}, |
| 414 | {{"\337\377\377", 3}, "3///"}, |
| 415 | {{"\277\377\377", 3}, "v///"}, |
| 416 | {{"\177\377\377", 3}, "f///"}, |
| 417 | |
| 418 | // Random numbers: values obtained with |
| 419 | // |
| 420 | // #! /bin/bash |
| 421 | // dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random |
| 422 | // od -N $1 -t o1 /tmp/bar.random |
| 423 | // uuencode -m test < /tmp/bar.random |
| 424 | // |
| 425 | // where $1 is the number of bytes (2, 3) |
| 426 | |
| 427 | {{"\243\361", 2}, "o/E="}, |
| 428 | {{"\024\167", 2}, "FHc="}, |
| 429 | {{"\313\252", 2}, "y6o="}, |
| 430 | {{"\046\041", 2}, "JiE="}, |
| 431 | {{"\145\236", 2}, "ZZ4="}, |
| 432 | {{"\254\325", 2}, "rNU="}, |
| 433 | {{"\061\330", 2}, "Mdg="}, |
| 434 | {{"\245\032", 2}, "pRo="}, |
| 435 | {{"\006\000", 2}, "BgA="}, |
| 436 | {{"\375\131", 2}, "/Vk="}, |
| 437 | {{"\303\210", 2}, "w4g="}, |
| 438 | {{"\040\037", 2}, "IB8="}, |
| 439 | {{"\261\372", 2}, "sfo="}, |
| 440 | {{"\335\014", 2}, "3Qw="}, |
| 441 | {{"\233\217", 2}, "m48="}, |
| 442 | {{"\373\056", 2}, "+y4="}, |
| 443 | {{"\247\232", 2}, "p5o="}, |
| 444 | {{"\107\053", 2}, "Rys="}, |
| 445 | {{"\204\077", 2}, "hD8="}, |
| 446 | {{"\276\211", 2}, "vok="}, |
| 447 | {{"\313\110", 2}, "y0g="}, |
| 448 | {{"\363\376", 2}, "8/4="}, |
| 449 | {{"\251\234", 2}, "qZw="}, |
| 450 | {{"\103\262", 2}, "Q7I="}, |
| 451 | {{"\142\312", 2}, "Yso="}, |
| 452 | {{"\067\211", 2}, "N4k="}, |
| 453 | {{"\220\001", 2}, "kAE="}, |
| 454 | {{"\152\240", 2}, "aqA="}, |
| 455 | {{"\367\061", 2}, "9zE="}, |
| 456 | {{"\133\255", 2}, "W60="}, |
| 457 | {{"\176\035", 2}, "fh0="}, |
| 458 | {{"\032\231", 2}, "Gpk="}, |
| 459 | |
| 460 | {{"\013\007\144", 3}, "Cwdk"}, |
| 461 | {{"\030\112\106", 3}, "GEpG"}, |
| 462 | {{"\047\325\046", 3}, "J9Um"}, |
| 463 | {{"\310\160\022", 3}, "yHAS"}, |
| 464 | {{"\131\100\237", 3}, "WUCf"}, |
| 465 | {{"\064\342\134", 3}, "NOJc"}, |
| 466 | {{"\010\177\004", 3}, "CH8E"}, |
| 467 | {{"\345\147\205", 3}, "5WeF"}, |
| 468 | {{"\300\343\360", 3}, "wOPw"}, |
| 469 | {{"\061\240\201", 3}, "MaCB"}, |
| 470 | {{"\225\333\044", 3}, "ldsk"}, |
| 471 | {{"\215\137\352", 3}, "jV/q"}, |
| 472 | {{"\371\147\160", 3}, "+Wdw"}, |
| 473 | {{"\030\320\051", 3}, "GNAp"}, |
| 474 | {{"\044\174\241", 3}, "JHyh"}, |
| 475 | {{"\260\127\037", 3}, "sFcf"}, |
| 476 | {{"\111\045\033", 3}, "SSUb"}, |
| 477 | {{"\202\114\107", 3}, "gkxH"}, |
| 478 | {{"\057\371\042", 3}, "L/ki"}, |
| 479 | {{"\223\247\244", 3}, "k6ek"}, |
| 480 | {{"\047\216\144", 3}, "J45k"}, |
| 481 | {{"\203\070\327", 3}, "gzjX"}, |
| 482 | {{"\247\140\072", 3}, "p2A6"}, |
| 483 | {{"\124\115\116", 3}, "VE1O"}, |
| 484 | {{"\157\162\050", 3}, "b3Io"}, |
| 485 | {{"\357\223\004", 3}, "75ME"}, |
| 486 | {{"\052\117\156", 3}, "Kk9u"}, |
| 487 | {{"\347\154\000", 3}, "52wA"}, |
| 488 | {{"\303\012\142", 3}, "wwpi"}, |
| 489 | {{"\060\035\362", 3}, "MB3y"}, |
| 490 | {{"\130\226\361", 3}, "WJbx"}, |
| 491 | {{"\173\013\071", 3}, "ews5"}, |
| 492 | {{"\336\004\027", 3}, "3gQX"}, |
| 493 | {{"\357\366\234", 3}, "7/ac"}, |
| 494 | {{"\353\304\111", 3}, "68RJ"}, |
| 495 | {{"\024\264\131", 3}, "FLRZ"}, |
| 496 | {{"\075\114\251", 3}, "PUyp"}, |
| 497 | {{"\315\031\225", 3}, "zRmV"}, |
| 498 | {{"\154\201\276", 3}, "bIG+"}, |
| 499 | {{"\200\066\072", 3}, "gDY6"}, |
| 500 | {{"\142\350\267", 3}, "Yui3"}, |
| 501 | {{"\033\000\166", 3}, "GwB2"}, |
| 502 | {{"\210\055\077", 3}, "iC0/"}, |
| 503 | {{"\341\037\124", 3}, "4R9U"}, |
| 504 | {{"\161\103\152", 3}, "cUNq"}, |
| 505 | {{"\270\142\131", 3}, "uGJZ"}, |
| 506 | {{"\337\076\074", 3}, "3z48"}, |
| 507 | {{"\375\106\362", 3}, "/Uby"}, |
| 508 | {{"\227\301\127", 3}, "l8FX"}, |
| 509 | {{"\340\002\234", 3}, "4AKc"}, |
| 510 | {{"\121\064\033", 3}, "UTQb"}, |
| 511 | {{"\157\134\143", 3}, "b1xj"}, |
| 512 | {{"\247\055\327", 3}, "py3X"}, |
| 513 | {{"\340\142\005", 3}, "4GIF"}, |
| 514 | {{"\060\260\143", 3}, "MLBj"}, |
| 515 | {{"\075\203\170", 3}, "PYN4"}, |
| 516 | {{"\143\160\016", 3}, "Y3AO"}, |
| 517 | {{"\313\013\063", 3}, "ywsz"}, |
| 518 | {{"\174\236\135", 3}, "fJ5d"}, |
| 519 | {{"\103\047\026", 3}, "QycW"}, |
| 520 | {{"\365\005\343", 3}, "9QXj"}, |
| 521 | {{"\271\160\223", 3}, "uXCT"}, |
| 522 | {{"\362\255\172", 3}, "8q16"}, |
| 523 | {{"\113\012\015", 3}, "SwoN"}, |
| 524 | |
| 525 | // various lengths, generated by this python script: |
| 526 | // |
| 527 | // from std::string import lowercase as lc |
| 528 | // for i in range(27): |
| 529 | // print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i), |
| 530 | // lc[:i].encode('base64').strip()) |
| 531 | |
| 532 | {{"", 0}, {"", 0}}, |
| 533 | {"a", "YQ=="}, |
| 534 | {"ab", "YWI="}, |
| 535 | {"abc", "YWJj"}, |
| 536 | {"abcd", "YWJjZA=="}, |
| 537 | {"abcde", "YWJjZGU="}, |
| 538 | {"abcdef", "YWJjZGVm"}, |
| 539 | {"abcdefg", "YWJjZGVmZw=="}, |
| 540 | {"abcdefgh", "YWJjZGVmZ2g="}, |
| 541 | {"abcdefghi", "YWJjZGVmZ2hp"}, |
| 542 | {"abcdefghij", "YWJjZGVmZ2hpag=="}, |
| 543 | {"abcdefghijk", "YWJjZGVmZ2hpams="}, |
| 544 | {"abcdefghijkl", "YWJjZGVmZ2hpamts"}, |
| 545 | {"abcdefghijklm", "YWJjZGVmZ2hpamtsbQ=="}, |
| 546 | {"abcdefghijklmn", "YWJjZGVmZ2hpamtsbW4="}, |
| 547 | {"abcdefghijklmno", "YWJjZGVmZ2hpamtsbW5v"}, |
| 548 | {"abcdefghijklmnop", "YWJjZGVmZ2hpamtsbW5vcA=="}, |
| 549 | {"abcdefghijklmnopq", "YWJjZGVmZ2hpamtsbW5vcHE="}, |
| 550 | {"abcdefghijklmnopqr", "YWJjZGVmZ2hpamtsbW5vcHFy"}, |
| 551 | {"abcdefghijklmnopqrs", "YWJjZGVmZ2hpamtsbW5vcHFycw=="}, |
| 552 | {"abcdefghijklmnopqrst", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q="}, |
| 553 | {"abcdefghijklmnopqrstu", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1"}, |
| 554 | {"abcdefghijklmnopqrstuv", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg=="}, |
| 555 | {"abcdefghijklmnopqrstuvw", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc="}, |
| 556 | {"abcdefghijklmnopqrstuvwx", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4"}, |
| 557 | {"abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ=="}, |
| 558 | {"abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="}, |
| 559 | }; |
| 560 | |
| 561 | template <typename StringType> |
| 562 | void TestEscapeAndUnescape() { |
| 563 | // Check the short strings; this tests the math (and boundaries) |
| 564 | for (const auto& tc : base64_tests) { |
| 565 | StringType encoded("this junk should be ignored"); |
| 566 | absl::Base64Escape(tc.plaintext, &encoded); |
| 567 | EXPECT_EQ(encoded, tc.cyphertext); |
| 568 | EXPECT_EQ(absl::Base64Escape(tc.plaintext), tc.cyphertext); |
| 569 | |
| 570 | StringType decoded("this junk should be ignored"); |
| 571 | EXPECT_TRUE(absl::Base64Unescape(encoded, &decoded)); |
| 572 | EXPECT_EQ(decoded, tc.plaintext); |
| 573 | |
| 574 | StringType websafe(tc.cyphertext); |
| 575 | for (int c = 0; c < websafe.size(); ++c) { |
| 576 | if ('+' == websafe[c]) websafe[c] = '-'; |
| 577 | if ('/' == websafe[c]) websafe[c] = '_'; |
| 578 | if ('=' == websafe[c]) { |
| 579 | websafe.resize(c); |
| 580 | break; |
| 581 | } |
| 582 | } |
| 583 | |
| 584 | encoded = "this junk should be ignored"; |
| 585 | absl::WebSafeBase64Escape(tc.plaintext, &encoded); |
| 586 | EXPECT_EQ(encoded, websafe); |
| 587 | EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe); |
| 588 | |
| 589 | // Let's try the std::string version of the decoder |
| 590 | decoded = "this junk should be ignored"; |
| 591 | EXPECT_TRUE(absl::WebSafeBase64Unescape(websafe, &decoded)); |
| 592 | EXPECT_EQ(decoded, tc.plaintext); |
| 593 | } |
| 594 | |
| 595 | // Now try the long strings, this tests the streaming |
| 596 | for (const auto& tc : absl::strings_internal::base64_strings()) { |
| 597 | StringType buffer; |
| 598 | absl::WebSafeBase64Escape(tc.plaintext, &buffer); |
| 599 | EXPECT_EQ(tc.cyphertext, buffer); |
| 600 | EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), tc.cyphertext); |
| 601 | } |
| 602 | |
| 603 | // Verify the behavior when decoding bad data |
| 604 | { |
| 605 | absl::string_view data_set[] = {"ab-/", absl::string_view("\0bcd", 4), |
| 606 | absl::string_view("abc.\0", 5)}; |
| 607 | for (absl::string_view bad_data : data_set) { |
| 608 | StringType buf; |
| 609 | EXPECT_FALSE(absl::Base64Unescape(bad_data, &buf)); |
| 610 | EXPECT_FALSE(absl::WebSafeBase64Unescape(bad_data, &buf)); |
| 611 | EXPECT_TRUE(buf.empty()); |
| 612 | } |
| 613 | } |
| 614 | } |
| 615 | |
| 616 | TEST(Base64, EscapeAndUnescape) { |
| 617 | TestEscapeAndUnescape<std::string>(); |
| 618 | } |
| 619 | |
| 620 | TEST(Base64, DISABLED_HugeData) { |
| 621 | const size_t kSize = size_t(3) * 1000 * 1000 * 1000; |
| 622 | static_assert(kSize % 3 == 0, "kSize must be divisible by 3"); |
| 623 | const std::string huge(kSize, 'x'); |
| 624 | |
| 625 | std::string escaped; |
| 626 | absl::Base64Escape(huge, &escaped); |
| 627 | |
| 628 | // Generates the std::string that should match a base64 encoded "xxx..." std::string. |
| 629 | // "xxx" in base64 is "eHh4". |
| 630 | std::string expected_encoding; |
| 631 | expected_encoding.reserve(kSize / 3 * 4); |
| 632 | for (size_t i = 0; i < kSize / 3; ++i) { |
| 633 | expected_encoding.append("eHh4"); |
| 634 | } |
| 635 | EXPECT_EQ(expected_encoding, escaped); |
| 636 | |
| 637 | std::string unescaped; |
| 638 | EXPECT_TRUE(absl::Base64Unescape(escaped, &unescaped)); |
| 639 | EXPECT_EQ(huge, unescaped); |
| 640 | } |
| 641 | |
| 642 | TEST(HexAndBack, HexStringToBytes_and_BytesToHexString) { |
| 643 | std::string hex_mixed = "0123456789abcdefABCDEF"; |
| 644 | std::string bytes_expected = "\x01\x23\x45\x67\x89\xab\xcd\xef\xAB\xCD\xEF"; |
| 645 | std::string hex_only_lower = "0123456789abcdefabcdef"; |
| 646 | |
| 647 | std::string bytes_result = absl::HexStringToBytes(hex_mixed); |
| 648 | EXPECT_EQ(bytes_expected, bytes_result); |
| 649 | |
| 650 | std::string prefix_valid = hex_mixed + "?"; |
| 651 | std::string prefix_valid_result = absl::HexStringToBytes( |
| 652 | absl::string_view(prefix_valid.data(), prefix_valid.size() - 1)); |
| 653 | EXPECT_EQ(bytes_expected, prefix_valid_result); |
| 654 | |
| 655 | std::string infix_valid = "?" + hex_mixed + "???"; |
| 656 | std::string infix_valid_result = absl::HexStringToBytes( |
| 657 | absl::string_view(infix_valid.data() + 1, hex_mixed.size())); |
| 658 | EXPECT_EQ(bytes_expected, infix_valid_result); |
| 659 | |
| 660 | std::string hex_result = absl::BytesToHexString(bytes_expected); |
| 661 | EXPECT_EQ(hex_only_lower, hex_result); |
| 662 | } |
| 663 | |
| 664 | } // namespace |