TestStandardURL.cpp (20985B)
1 #include "gtest/gtest.h" 2 #include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH 3 4 #include "nsCOMPtr.h" 5 #include "nsNetCID.h" 6 #include "nsIURL.h" 7 #include "nsIStandardURL.h" 8 #include "nsString.h" 9 #include "nsPrintfCString.h" 10 #include "nsComponentManagerUtils.h" 11 #include "nsIURIMutator.h" 12 #include "mozilla/ipc/URIUtils.h" 13 #include "nsSerializationHelper.h" 14 #include "mozilla/Base64.h" 15 #include "nsEscape.h" 16 #include "nsURLHelper.h" 17 #include "IPv4Parser.h" 18 19 using namespace mozilla; 20 21 nsresult Test_NormalizeIPv4(const nsACString& host, nsCString& result) { 22 return net::IPv4Parser::NormalizeIPv4(host, result); 23 } 24 25 TEST(TestStandardURL, Simple) 26 { 27 nsCOMPtr<nsIURI> url; 28 ASSERT_EQ(NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 29 .SetSpec("http://example.com"_ns) 30 .Finalize(url), 31 NS_OK); 32 ASSERT_TRUE(url); 33 34 ASSERT_EQ(NS_MutateURI(url).SetSpec("http://example.com"_ns).Finalize(url), 35 NS_OK); 36 37 nsAutoCString out; 38 39 ASSERT_EQ(url->GetSpec(out), NS_OK); 40 ASSERT_TRUE(out == "http://example.com/"_ns); 41 42 ASSERT_EQ(url->Resolve("foo.html?q=45"_ns, out), NS_OK); 43 ASSERT_TRUE(out == "http://example.com/foo.html?q=45"_ns); 44 45 ASSERT_EQ(NS_MutateURI(url).SetScheme("foo"_ns).Finalize(url), NS_OK); 46 47 ASSERT_EQ(url->GetScheme(out), NS_OK); 48 ASSERT_TRUE(out == "foo"_ns); 49 50 ASSERT_EQ(url->GetHost(out), NS_OK); 51 ASSERT_TRUE(out == "example.com"_ns); 52 ASSERT_EQ(NS_MutateURI(url).SetHost("www.yahoo.com"_ns).Finalize(url), NS_OK); 53 ASSERT_EQ(url->GetHost(out), NS_OK); 54 ASSERT_TRUE(out == "www.yahoo.com"_ns); 55 56 ASSERT_EQ(NS_MutateURI(url) 57 .SetPathQueryRef(nsLiteralCString( 58 "/some-path/one-the-net/about.html?with-a-query#for-you")) 59 .Finalize(url), 60 NS_OK); 61 ASSERT_EQ(url->GetPathQueryRef(out), NS_OK); 62 ASSERT_TRUE(out == 63 nsLiteralCString( 64 "/some-path/one-the-net/about.html?with-a-query#for-you")); 65 66 ASSERT_EQ(NS_MutateURI(url) 67 .SetQuery(nsLiteralCString( 68 "a=b&d=c&what-ever-you-want-to-be-called=45")) 69 .Finalize(url), 70 NS_OK); 71 ASSERT_EQ(url->GetQuery(out), NS_OK); 72 ASSERT_TRUE(out == "a=b&d=c&what-ever-you-want-to-be-called=45"_ns); 73 74 ASSERT_EQ(NS_MutateURI(url).SetRef("#some-book-mark"_ns).Finalize(url), 75 NS_OK); 76 ASSERT_EQ(url->GetRef(out), NS_OK); 77 ASSERT_TRUE(out == "some-book-mark"_ns); 78 } 79 80 TEST(TestStandardURL, NormalizeGood) 81 { 82 nsCString result; 83 const char* manual[] = {"0.0.0.0", 84 "0.0.0.0", 85 "0", 86 "0.0.0.0", 87 "000", 88 "0.0.0.0", 89 "0x00", 90 "0.0.0.0", 91 "10.20.100.200", 92 "10.20.100.200", 93 "255.255.255.255", 94 "255.255.255.255", 95 "0XFF.0xFF.0xff.0xFf", 96 "255.255.255.255", 97 "0x000ff.0X00FF.0x0ff.0xff", 98 "255.255.255.255", 99 "0x000fA.0X00FB.0x0fC.0xfD", 100 "250.251.252.253", 101 "0x000fE.0X00FF.0x0fC.0xfD", 102 "254.255.252.253", 103 "0x000fa.0x00fb.0x0fc.0xfd", 104 "250.251.252.253", 105 "0x000fe.0x00ff.0x0fc.0xfd", 106 "254.255.252.253", 107 "0377.0377.0377.0377", 108 "255.255.255.255", 109 "0000377.000377.00377.0377", 110 "255.255.255.255", 111 "65535", 112 "0.0.255.255", 113 "0xfFFf", 114 "0.0.255.255", 115 "0x00000ffff", 116 "0.0.255.255", 117 "0177777", 118 "0.0.255.255", 119 "000177777", 120 "0.0.255.255", 121 "0.13.65535", 122 "0.13.255.255", 123 "0.22.0xffff", 124 "0.22.255.255", 125 "0.123.0177777", 126 "0.123.255.255", 127 "65536", 128 "0.1.0.0", 129 "0200000", 130 "0.1.0.0", 131 "0x10000", 132 "0.1.0.0"}; 133 for (uint32_t i = 0; i < sizeof(manual) / sizeof(manual[0]); i += 2) { 134 nsCString encHost(manual[i + 0]); 135 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result)); 136 ASSERT_TRUE(result.Equals(manual[i + 1])); 137 } 138 139 // Make sure we're getting the numbers correctly interpreted: 140 for (int i = 0; i < 256; i++) { 141 nsCString encHost = nsPrintfCString("0x%x", i); 142 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result)); 143 ASSERT_TRUE(result.Equals(nsPrintfCString("0.0.0.%d", i))); 144 145 encHost = nsPrintfCString("0%o", i); 146 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result)); 147 ASSERT_TRUE(result.Equals(nsPrintfCString("0.0.0.%d", i))); 148 } 149 150 // Some random numbers in the range, mixing hex, decimal, octal 151 for (int i = 0; i < 8; i++) { 152 int val[4] = {i * 11 + 13, i * 18 + 22, i * 4 + 28, i * 15 + 2}; 153 154 nsCString encHost = 155 nsPrintfCString("%d.%d.%d.%d", val[0], val[1], val[2], val[3]); 156 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result)); 157 ASSERT_TRUE(result.Equals(encHost)); 158 159 nsCString encHostM = 160 nsPrintfCString("0x%x.0x%x.0x%x.0x%x", val[0], val[1], val[2], val[3]); 161 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result)); 162 ASSERT_TRUE(result.Equals(encHost)); 163 164 encHostM = 165 nsPrintfCString("0%o.0%o.0%o.0%o", val[0], val[1], val[2], val[3]); 166 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result)); 167 ASSERT_TRUE(result.Equals(encHost)); 168 169 encHostM = 170 nsPrintfCString("0x%x.%d.0%o.%d", val[0], val[1], val[2], val[3]); 171 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result)); 172 ASSERT_TRUE(result.Equals(encHost)); 173 174 encHostM = 175 nsPrintfCString("%d.0%o.0%o.0x%x", val[0], val[1], val[2], val[3]); 176 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result)); 177 ASSERT_TRUE(result.Equals(encHost)); 178 179 encHostM = 180 nsPrintfCString("0%o.0%o.0x%x.0x%x", val[0], val[1], val[2], val[3]); 181 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHostM, result)); 182 ASSERT_TRUE(result.Equals(encHost)); 183 } 184 } 185 186 TEST(TestStandardURL, NormalizeBad) 187 { 188 nsAutoCString result; 189 const char* manual[] = { 190 "x22.232.12.32", "122..12.32", "122.12.32.12.32", "122.12.32..", 191 "122.12.xx.22", "122.12.0xx.22", "0xx.12.01.22", "12.12.02x.22", 192 "1q.12.2.22", "122.01f.02.22", "12a.01.02.22", "12.01.02.20x1", 193 "10x2.01.02.20", "0xx.01.02.20", "10.x.02.20", "10.00x2.02.20", 194 "10.13.02x2.20", "10.x13.02.20", "10.0x134def.02.20", "\0.2.2.2", 195 "256.2.2.2", "2.256.2.2", "2.2.256.2", "2.2.2.256", 196 "2.2.-2.3", "+2.2.2.3", "13.0x2x2.2.3", "0x2x2.13.2.3"}; 197 198 for (auto& i : manual) { 199 nsCString encHost(i); 200 ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost, result)); 201 } 202 } 203 204 TEST(TestStandardURL, From_test_standardurldotjs) 205 { 206 // These are test (success and failure) cases from test_standardurl.js 207 nsAutoCString result; 208 209 const char* localIPv4s[] = { 210 "127.0.0.1", 211 "127.0.1", 212 "127.1", 213 "2130706433", 214 "0177.00.00.01", 215 "0177.00.01", 216 "0177.01", 217 "00000000000000000000000000177.0000000.0000000.0001", 218 "000000177.0000001", 219 "017700000001", 220 "0x7f.0x00.0x00.0x01", 221 "0x7f.0x01", 222 "0x7f000001", 223 "0x007f.0x0000.0x0000.0x0001", 224 "000177.0.00000.0x0001", 225 "127.0.0.1.", 226 227 "0X7F.0X00.0X00.0X01", 228 "0X7F.0X01", 229 "0X7F000001", 230 "0X007F.0X0000.0X0000.0X0001", 231 "000177.0.00000.0X0001"}; 232 for (auto& localIPv4 : localIPv4s) { 233 nsCString encHost(localIPv4); 234 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result)); 235 ASSERT_TRUE(result.EqualsLiteral("127.0.0.1")); 236 } 237 238 const char* nonIPv4s[] = {"0xfffffffff", "0x100000000", 239 "4294967296", "1.2.0x10000", 240 "1.0x1000000", "256.0.0.1", 241 "1.256.1", "-1.0.0.0", 242 "1.2.3.4.5", "010000000000000000", 243 "2+3", "0.0.0.-1", 244 "1.2.3.4..", "1..2", 245 ".1.2.3.4", ".127"}; 246 for (auto& nonIPv4 : nonIPv4s) { 247 nsCString encHost(nonIPv4); 248 ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost, result)); 249 } 250 251 const char* oneOrNoDotsIPv4s[] = {"127", "127."}; 252 for (auto& localIPv4 : oneOrNoDotsIPv4s) { 253 nsCString encHost(localIPv4); 254 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result)); 255 ASSERT_TRUE(result.EqualsLiteral("0.0.0.127")); 256 } 257 } 258 259 #define TEST_COUNT 10000 260 261 MOZ_GTEST_BENCH(TestStandardURL, DISABLED_Perf, [] { 262 nsCOMPtr<nsIURI> url; 263 ASSERT_EQ(NS_OK, NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 264 .SetSpec("http://example.com"_ns) 265 .Finalize(url)); 266 267 nsAutoCString out; 268 for (int i = TEST_COUNT; i; --i) { 269 ASSERT_EQ(NS_MutateURI(url).SetSpec("http://example.com"_ns).Finalize(url), 270 NS_OK); 271 ASSERT_EQ(url->GetSpec(out), NS_OK); 272 url->Resolve("foo.html?q=45"_ns, out); 273 (void)NS_MutateURI(url).SetScheme("foo"_ns).Finalize(url); 274 url->GetScheme(out); 275 (void)NS_MutateURI(url).SetHost("www.yahoo.com"_ns).Finalize(url); 276 url->GetHost(out); 277 (void)NS_MutateURI(url) 278 .SetPathQueryRef(nsLiteralCString( 279 "/some-path/one-the-net/about.html?with-a-query#for-you")) 280 .Finalize(url); 281 url->GetPathQueryRef(out); 282 (void)NS_MutateURI(url) 283 .SetQuery( 284 nsLiteralCString("a=b&d=c&what-ever-you-want-to-be-called=45")) 285 .Finalize(url); 286 url->GetQuery(out); 287 (void)NS_MutateURI(url).SetRef("#some-book-mark"_ns).Finalize(url); 288 url->GetRef(out); 289 } 290 }); 291 292 // Note the five calls in the loop, so divide by 100k 293 MOZ_GTEST_BENCH(TestStandardURL, DISABLED_NormalizePerf, [] { 294 nsAutoCString result; 295 for (int i = 0; i < 20000; i++) { 296 nsAutoCString encHost("123.232.12.32"); 297 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost, result)); 298 nsAutoCString encHost2("83.62.12.92"); 299 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost2, result)); 300 nsAutoCString encHost3("8.7.6.5"); 301 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost3, result)); 302 nsAutoCString encHost4("111.159.123.220"); 303 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost4, result)); 304 nsAutoCString encHost5("1.160.204.200"); 305 ASSERT_EQ(NS_OK, Test_NormalizeIPv4(encHost5, result)); 306 } 307 }); 308 309 // Bug 1394785 - ignore unstable test on OSX 310 #ifndef XP_MACOSX 311 // Note the five calls in the loop, so divide by 100k 312 MOZ_GTEST_BENCH(TestStandardURL, DISABLED_NormalizePerfFails, [] { 313 nsAutoCString result; 314 for (int i = 0; i < 20000; i++) { 315 nsAutoCString encHost("123.292.12.32"); 316 ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost, result)); 317 nsAutoCString encHost2("83.62.12.0x13292"); 318 ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost2, result)); 319 nsAutoCString encHost3("8.7.6.0xhello"); 320 ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost3, result)); 321 nsAutoCString encHost4("111.159.notonmywatch.220"); 322 ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost4, result)); 323 nsAutoCString encHost5("1.160.204.20f"); 324 ASSERT_EQ(NS_ERROR_FAILURE, Test_NormalizeIPv4(encHost5, result)); 325 } 326 }); 327 #endif 328 329 TEST(TestStandardURL, Mutator) 330 { 331 nsAutoCString out; 332 nsCOMPtr<nsIURI> uri; 333 nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 334 .SetSpec("http://example.com"_ns) 335 .Finalize(uri); 336 ASSERT_EQ(rv, NS_OK); 337 338 ASSERT_EQ(uri->GetSpec(out), NS_OK); 339 ASSERT_TRUE(out == "http://example.com/"_ns); 340 341 rv = NS_MutateURI(uri) 342 .SetScheme("ftp"_ns) 343 .SetHost("mozilla.org"_ns) 344 .SetPathQueryRef("/path?query#ref"_ns) 345 .Finalize(uri); 346 ASSERT_EQ(rv, NS_OK); 347 ASSERT_EQ(uri->GetSpec(out), NS_OK); 348 ASSERT_TRUE(out == "ftp://mozilla.org/path?query#ref"_ns); 349 350 nsCOMPtr<nsIURL> url; 351 rv = NS_MutateURI(uri).SetScheme("https"_ns).Finalize(url); 352 ASSERT_EQ(rv, NS_OK); 353 ASSERT_EQ(url->GetSpec(out), NS_OK); 354 ASSERT_TRUE(out == "https://mozilla.org/path?query#ref"_ns); 355 } 356 357 TEST(TestStandardURL, Deserialize_Bug1392739) 358 { 359 mozilla::ipc::StandardURLParams standard_params; 360 standard_params.urlType() = nsIStandardURL::URLTYPE_STANDARD; 361 standard_params.spec().Truncate(); 362 standard_params.host() = mozilla::ipc::StandardURLSegment(4294967295, 1); 363 364 mozilla::ipc::URIParams params(standard_params); 365 366 nsCOMPtr<nsIURIMutator> mutator = 367 do_CreateInstance(NS_STANDARDURLMUTATOR_CID); 368 ASSERT_EQ(mutator->Deserialize(params), NS_ERROR_FAILURE); 369 } 370 371 TEST(TestStandardURL, CorruptSerialization) 372 { 373 auto spec = "http://user:pass@example.com/path/to/file.ext?query#hash"_ns; 374 375 nsCOMPtr<nsIURI> uri; 376 nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 377 .SetSpec(spec) 378 .Finalize(uri); 379 ASSERT_EQ(rv, NS_OK); 380 381 nsAutoCString serialization; 382 nsCOMPtr<nsISerializable> serializable = do_QueryInterface(uri); 383 ASSERT_TRUE(serializable); 384 385 // Check that the URL is normally serializable. 386 ASSERT_EQ(NS_OK, NS_SerializeToString(serializable, serialization)); 387 nsCOMPtr<nsISupports> deserializedObject; 388 ASSERT_EQ(NS_OK, NS_DeserializeObject(serialization, 389 getter_AddRefs(deserializedObject))); 390 391 nsAutoCString canonicalBin; 392 (void)Base64Decode(serialization, canonicalBin); 393 394 // The spec serialization begins at byte 49 395 // If the implementation of nsStandardURL::Write changes, this test will need 396 // to be adjusted. 397 #define SPEC_OFFSET 49 398 399 ASSERT_EQ(Substring(canonicalBin, SPEC_OFFSET, 7), "http://"_ns); 400 401 nsAutoCString corruptedBin = canonicalBin; 402 // change mScheme.mPos 403 corruptedBin.BeginWriting()[SPEC_OFFSET + spec.Length()] = 1; 404 (void)Base64Encode(corruptedBin, serialization); 405 ASSERT_EQ( 406 NS_ERROR_MALFORMED_URI, 407 NS_DeserializeObject(serialization, getter_AddRefs(deserializedObject))); 408 409 corruptedBin = canonicalBin; 410 // change mScheme.mLen 411 corruptedBin.BeginWriting()[SPEC_OFFSET + spec.Length() + 4] = 127; 412 (void)Base64Encode(corruptedBin, serialization); 413 ASSERT_EQ( 414 NS_ERROR_MALFORMED_URI, 415 NS_DeserializeObject(serialization, getter_AddRefs(deserializedObject))); 416 } 417 418 TEST(TestStandardURL, ParseIPv4Num) 419 { 420 auto host = "0x.0x.0"_ns; 421 422 int32_t bases[4] = {10, 10, 10, 10}; 423 bool onlyBase10 = true; // Track this as a special case 424 int32_t dotIndex[3]; // The positions of the dots in the string 425 int32_t length = static_cast<int32_t>(host.Length()); 426 427 ASSERT_EQ(2, mozilla::net::IPv4Parser::ValidateIPv4Number( 428 host, bases, dotIndex, onlyBase10, length, false)); 429 430 nsCString result; 431 ASSERT_EQ(NS_OK, Test_NormalizeIPv4("0x.0x.0"_ns, result)); 432 433 uint32_t number; 434 mozilla::net::IPv4Parser::ParseIPv4Number("0x10"_ns, 16, number, 255); 435 ASSERT_EQ(number, (uint32_t)16); 436 } 437 438 TEST(TestStandardURL, CoalescePath) 439 { 440 auto testCoalescing = [](const char* input, const char* expected, 441 uint32_t lastSlash, uint32_t endOfBasename) { 442 nsAutoCString buf(input); 443 auto resultCoalesceDirs = net_CoalesceDirs(buf.BeginWriting()); 444 445 ASSERT_EQ(nsCString(buf.get()), nsCString(expected)); 446 447 // If the path does not begin with '/', it should return Nothing(). 448 if (input[0] == '/') { 449 ASSERT_EQ(resultCoalesceDirs->first(), lastSlash); 450 ASSERT_EQ(resultCoalesceDirs->second(), endOfBasename); 451 } else { 452 ASSERT_TRUE(resultCoalesceDirs == Nothing()); 453 } 454 }; 455 456 #ifndef DEBUG 457 // invalid input 458 testCoalescing("", "", -1, -1); 459 #endif 460 // end of basename is the null character's index 461 testCoalescing("/", "/", 0, 1); 462 testCoalescing("/.", "/", 0, 1); 463 testCoalescing("/..", "/", 0, 1); 464 testCoalescing("/foo/foo1/.", "/foo/foo1/", 9, 10); 465 testCoalescing("/foo/../foo1", "/foo1", 0, 5); 466 testCoalescing("/foo/./foo1", "/foo/foo1", 4, 9); 467 testCoalescing("/foo/foo1/..", "/foo/", 4, 5); 468 469 // Bug 1890346 470 testCoalescing("/..?/..", "/?/..", 0, 1); 471 472 testCoalescing("/.?/..", "/?/..", 0, 1); 473 testCoalescing("/./../?", "/?", 0, 1); 474 testCoalescing("/.abc", "/.abc", 0, 5); 475 testCoalescing("//", "//", 1, 2); 476 testCoalescing("/../", "/", 0, 1); 477 testCoalescing("/./", "/", 0, 1); 478 testCoalescing("/.../", "/.../", 4, 5); 479 480 // Bug 1873915 481 testCoalescing("/hello/%2e%2e/foo", "/foo", 0, 4); 482 testCoalescing("/hello/%2e%2E/foo", "/foo", 0, 4); 483 testCoalescing("/hello/%2E%2e/foo", "/foo", 0, 4); 484 testCoalescing("/hello/%2E%2E/foo", "/foo", 0, 4); 485 testCoalescing("/hello/%2e./foo", "/foo", 0, 4); 486 testCoalescing("/hello/.%2e/foo", "/foo", 0, 4); 487 testCoalescing("/hello/%2E./foo", "/foo", 0, 4); 488 testCoalescing("/hello/.%2E/foo", "/foo", 0, 4); 489 testCoalescing("/hello/%2e%2E/%2e", "/", 0, 1); 490 testCoalescing("/hello/%2e/%2e%2e", "/", 0, 1); 491 testCoalescing("/hello/%2e%2E/%#", "/%#", 0, 2); 492 testCoalescing("/hello/%2e%2E/%?", "/%?", 0, 2); 493 testCoalescing("/hello/%2e", "/hello/", 6, 7); 494 testCoalescing("/hello/%2E", "/hello/", 6, 7); 495 testCoalescing("/hello/%2e/", "/hello/", 6, 7); 496 testCoalescing("/hello/%2E/", "/hello/", 6, 7); 497 testCoalescing("/hello/%2e.", "/", 0, 1); 498 testCoalescing("/hello/.%2e", "/", 0, 1); 499 testCoalescing("/hello/%2E.", "/", 0, 1); 500 testCoalescing("/hello/.%2E", "/", 0, 1); 501 testCoalescing("/hello/%2E%2e/%2e/./../.", "/", 0, 1); 502 testCoalescing("/test/%2e%2e/dir/%2E%2e/file", "/file", 0, 5); 503 504 // should not convert as a character is present 505 testCoalescing("/hello/%2E%2ea", "/hello/%2E%2ea", 6, 14); 506 testCoalescing("/hello/a%2E%2e", "/hello/a%2E%2e", 6, 14); 507 testCoalescing("/hello/a%2E%2ea", "/hello/a%2E%2ea", 6, 15); 508 509 // Encoded sequences followed by special characters 510 testCoalescing("/foo/%2e%2e/%2e%23/file.txt", "/%2e%23/file.txt", 7, 16); 511 testCoalescing("/foo/%2e%2e/%2e%3f/file.txt", "/%2e%3f/file.txt", 7, 16); 512 513 // Query strings and fragments with encoded sequences 514 testCoalescing("/query/%2e%2e/path?p=%2e", "/path?p=%2e", 0, 5); 515 testCoalescing("/frag/%2e%2e/path#q=%2e", "/path#q=%2e", 0, 5); 516 517 // 3 or more "%2e" repeating should not convert to "." 518 testCoalescing("/hello/%2E%2e%2E", "/hello/%2E%2e%2E", 6, 16); 519 testCoalescing("/hello/%2E%2e%2E%2e", "/hello/%2E%2e%2E%2e", 6, 19); 520 testCoalescing("/hello/%2E%2e%2E%2e.", "/hello/%2E%2e%2E%2e.", 6, 20); 521 522 // Relatively long inputs 523 testCoalescing("/foo/bar/foo/bar/foo/bar/foo/bar/foo?query#frag", 524 "/foo/bar/foo/bar/foo/bar/foo/bar/foo?query#frag", 32, 36); 525 526 testCoalescing("/coder/coder/edit/main/docs/./enterprise.md", 527 "/coder/coder/edit/main/docs/enterprise.md", 27, 41); 528 529 // bug 1942820 530 testCoalescing("/foo/bar/.%2e", "/foo/", 4, 5); 531 testCoalescing("/foo/bar/..", "/foo/", 4, 5); 532 testCoalescing("/foo/bar/%2e%2e", "/foo/", 4, 5); 533 testCoalescing("/foo/bar/%2e%2e#frag", "/foo/#frag", 4, 5); 534 testCoalescing("/foo/bar/%2e%2e?query", "/foo/?query", 4, 5); 535 } 536 537 TEST(TestStandardURL, bug1904582) 538 { 539 auto spec = "x:///%2e%2e"_ns; 540 541 nsCOMPtr<nsIURI> uri; 542 nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 543 .SetSpec(spec) 544 .Finalize(uri); 545 ASSERT_TRUE(NS_SUCCEEDED(rv)); 546 } 547 548 TEST(TestStandardURL, bug1911529) 549 { 550 nsCOMPtr<nsIURI> uri; 551 nsresult rv = 552 NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 553 .SetSpec( 554 "https://github.com/coder/coder/edit/main/docs/./enterprise.md"_ns) 555 .Finalize(uri); 556 ASSERT_TRUE(NS_SUCCEEDED(rv)); 557 558 nsAutoCString out; 559 ASSERT_EQ(uri->GetSpec(out), NS_OK); 560 ASSERT_TRUE(out == 561 "https://github.com/coder/coder/edit/main/docs/enterprise.md"_ns); 562 563 nsCOMPtr<nsIURI> uri2; 564 rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 565 .SetSpec( 566 "https://github.com/coder/coder/edit/main/docs/enterprise.md"_ns) 567 .Finalize(uri2); 568 ASSERT_TRUE(NS_SUCCEEDED(rv)); 569 570 bool equals = false; 571 ASSERT_EQ(uri->Equals(uri2, &equals), NS_OK); 572 ASSERT_TRUE(equals); 573 574 rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 575 .SetSpec("https://domain.com/."_ns) 576 .Finalize(uri); 577 ASSERT_TRUE(NS_SUCCEEDED(rv)); 578 rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID) 579 .SetSpec("https://domain.com/"_ns) 580 .Finalize(uri2); 581 ASSERT_TRUE(NS_SUCCEEDED(rv)); 582 583 ASSERT_EQ(uri->Equals(uri2, &equals), NS_OK); 584 ASSERT_TRUE(equals); 585 }