diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart index 3da4e8f1452..dd498d2ed63 100644 --- a/sdk/lib/core/uri.dart +++ b/sdk/lib/core/uri.dart @@ -2276,7 +2276,7 @@ final class _Uri implements _PlatformUri { if ((char & 0xFC00) == 0xD800 && (index + 1) < end) { int tail = host.codeUnitAt(index + 1); if ((tail & 0xFC00) == 0xDC00) { - char = 0x10000 | ((char & 0x3ff) << 10) | (tail & 0x3ff); + char = 0x10000 + ((char & 0x3ff) << 10) + (tail & 0x3ff); sourceLength = 2; } } @@ -2354,7 +2354,7 @@ final class _Uri implements _PlatformUri { if ((char & 0xFC00) == 0xD800 && (index + 1) < end) { int tail = host.codeUnitAt(index + 1); if ((tail & 0xFC00) == 0xDC00) { - char = 0x10000 | ((char & 0x3ff) << 10) | (tail & 0x3ff); + char = 0x10000 + ((char & 0x3ff) << 10) + (tail & 0x3ff); sourceLength = 2; } } @@ -2580,7 +2580,7 @@ final class _Uri implements _PlatformUri { static String _escapeChar(int char) { assert(char <= 0x10ffff); // It's a valid unicode code point. List codeUnits; - if (char < 0x80) { + if (char <= 0x7f) { // ASCII, a single percent encoded sequence. codeUnits = Uint8List(3); codeUnits[0] = _PERCENT; @@ -2692,7 +2692,7 @@ final class _Uri implements _PlatformUri { if ((tail & 0xFC00) == 0xDC00) { // Tail surrogate. sourceLength = 2; - char = 0x10000 | ((char & 0x3ff) << 10) | (tail & 0x3ff); + char = 0x10000 + ((char & 0x3ff) << 10) + (tail & 0x3ff); } } } diff --git a/tests/corelib/uri_test.dart b/tests/corelib/uri_test.dart index ffc7fb79a0c..042f3cf1064 100644 --- a/tests/corelib/uri_test.dart +++ b/tests/corelib/uri_test.dart @@ -879,6 +879,28 @@ main() { testReplace(); testPackageUris(); testBackslashes(); + + testNonBmpEncodingRegression(); +} + +void testNonBmpEncodingRegression() { + // Regression test for bug in encoding of some non-BMP characters + // in host names. The failing character has to be one that doesn't have + // the 0x10000 bit set in its code point, and which is not in the BMP. + const char = "\u{2003E}"; // CJK Unified Ideo­graph. + const echar = "%F0%A0%80%BE"; // UTF-8 encoding of page2Char, %-encoded. + var nonBmpUri = + Uri.parse("http://$char.example.com/x${char}x?y${char}y#z${char}z"); + Expect.equals("http://$echar.example.com/x${echar}x?y${echar}y#z${echar}z", + nonBmpUri.toString()); + Expect.equals("$echar.example.com", nonBmpUri.host); + Expect.equals("$char.example.com", Uri.decodeComponent(nonBmpUri.host)); + Expect.equals("/x${echar}x", nonBmpUri.path); + Expect.equals("/x${char}x", Uri.decodeComponent(nonBmpUri.path)); + Expect.equals("y${echar}y", nonBmpUri.query); + Expect.equals("y${char}y", Uri.decodeComponent(nonBmpUri.query)); + Expect.equals("z${echar}z", nonBmpUri.fragment); + Expect.equals("z${char}z", Uri.decodeComponent(nonBmpUri.fragment)); } String dump(Uri uri) {