diff --git a/include/ada/checkers-inl.h b/include/ada/checkers-inl.h index 950b1cb5a..a4c8c8371 100644 --- a/include/ada/checkers-inl.h +++ b/include/ada/checkers-inl.h @@ -47,7 +47,7 @@ constexpr bool is_windows_drive_letter(std::string_view input) noexcept { constexpr bool is_normalized_windows_drive_letter( std::string_view input) noexcept { - return input.size() >= 2 && (is_alpha(input[0]) && (input[1] == ':')); + return input.size() == 2 && (is_alpha(input[0]) && (input[1] == ':')); } ada_really_inline constexpr uint64_t try_parse_ipv4_fast( diff --git a/tests/basic_tests.cpp b/tests/basic_tests.cpp index f621fb582..7f85e7eb4 100644 --- a/tests/basic_tests.cpp +++ b/tests/basic_tests.cpp @@ -108,6 +108,18 @@ TYPED_TEST(basic_tests, readme2) { SUCCEED(); } +TYPED_TEST(basic_tests, file_shorten_path_normalized_drive_letter_only) { + // https://url.spec.whatwg.org/#shorten-a-urls-path : a file path's first + // segment is protected from ".." only when it is a *normalized Windows drive + // letter*, which is exactly two code points (an ASCII alpha followed by ":"). + // Longer segments that merely start with ":" must be popped. + ASSERT_EQ(ada::parse("file:c:x/..")->get_href(), "file:///"); + ASSERT_EQ(ada::parse("file:u:p@h/..")->get_href(), "file:///"); + // A real drive letter is still preserved. + ASSERT_EQ(ada::parse("file:c:/..")->get_href(), "file:///c:/"); + SUCCEED(); +} + TYPED_TEST(basic_tests, readme2free) { auto url = ada::parse("https://www.google.com"); url->set_username("username");