Commit 41282000 authored by Dominik Charousset's avatar Dominik Charousset

Fix URI edge cases for paths and curly braces

parent b05a4b7b
......@@ -69,7 +69,8 @@ void read_uri_percent_encoded(State& ps, std::string& str) {
}
inline bool uri_unprotected_char(char c) {
return in_whitelist(alphanumeric_chars, c) || in_whitelist("-._~", c);
// Consider valid characters not explicitly stated as reserved as unreserved.
return isprint(c) && !in_whitelist(":/?#[]@!$&'()*+,;=", c);
}
// clang-format off
......@@ -129,7 +130,9 @@ void read_uri(State& ps, Consumer&& consumer) {
return res;
};
// Allowed character sets.
auto path_char = [](char c) { return uri_unprotected_char(c) || c == '/'; };
auto path_char = [](char c) {
return uri_unprotected_char(c) || c == '/' || c == ':';
};
// Utility setters for avoiding code duplication.
auto set_path = [&] { consumer.path(take_str()); };
auto set_host = [&] { consumer.host(take_str()); };
......@@ -161,6 +164,8 @@ void read_uri(State& ps, Consumer&& consumer) {
epsilon(read_path, any_char, str += '/')
}
state(start_authority) {
// A third '/' skips the authority, e.g., "file:///".
transition(read_path, '/', str += '/')
read_next_char(read_authority, str)
fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
}
......
......@@ -28,6 +28,7 @@ namespace detail {
void append_percent_encoded(std::string& str, string_view x, bool is_path) {
for (auto ch : x)
switch (ch) {
case ':':
case '/':
if (is_path) {
str += ch;
......@@ -35,7 +36,6 @@ void append_percent_encoded(std::string& str, string_view x, bool is_path) {
}
CAF_ANNOTATE_FALLTHROUGH;
case ' ':
case ':':
case '?':
case '#':
case '[':
......
......@@ -289,6 +289,7 @@ CAF_TEST(from string) {
// all combinations of components
ROUNDTRIP("http:file");
ROUNDTRIP("http:foo-bar");
ROUNDTRIP("http:foo:bar");
ROUNDTRIP("http:file?a=1&b=2");
ROUNDTRIP("http:file#42");
ROUNDTRIP("http:file?a=1&b=2#42");
......@@ -359,12 +360,14 @@ CAF_TEST(from string) {
ROUNDTRIP("http://me@[::1]:80/file?a=1&b=2#42");
// percent encoding
ROUNDTRIP("hi%20there://it%27s@me%21/file%201#%5B42%5D");
ROUNDTRIP("file://localhost/tmp/test/test.{%3A04d}.exr");
}
#undef ROUNDTRIP
CAF_TEST(empty components) {
CAF_CHECK_EQUAL("foo:/"_u, "foo:/");
CAF_CHECK_EQUAL("foo:///"_u, "foo:/");
CAF_CHECK_EQUAL("foo:/#"_u, "foo:/");
CAF_CHECK_EQUAL("foo:/?"_u, "foo:/");
CAF_CHECK_EQUAL("foo:/?#"_u, "foo:/");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment