Skip to content

Commit 866d3ff

Browse files
Fix URI fragment parsing without query (#6393)
- Stops URI authority and path parsing at query/fragment delimiters. - Only parses a query when ? is present, so path#fragment reaches the fragment parser. - Adds URI parser coverage for fragment cases with and without a path/query. Signed-off-by: Minh Vu <vuhoangminh97@gmail.com>
1 parent 7144a16 commit 866d3ff

2 files changed

Lines changed: 66 additions & 14 deletions

File tree

dali/util/uri.cc

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ URI URI::Parse(std::string uri, URI::ParseOpts opts) {
104104
if (*p == '/' && *(p + 1) == '/') {
105105
p += 2;
106106
parsed.authority_start_ = p - p_start;
107-
while (*p != '\0' && *p != '/') {
107+
while (*p != '\0' && *p != '/' && *p != '?' && *p != '#') {
108108
if (!allowed_char(*p)) {
109109
parsed.valid_ = false;
110110
parsed.err_msg_ = "Invalid character found (" + display_char(*p) + ") in authority";
@@ -123,7 +123,7 @@ URI URI::Parse(std::string uri, URI::ParseOpts opts) {
123123

124124
// Path
125125
parsed.path_start_ = p - p_start;
126-
while (*p != '\0' && *p != '?') {
126+
while (*p != '\0' && *p != '?' && *p != '#') {
127127
if (!allowed_char(*p) && !allow_non_escaped) {
128128
parsed.valid_ = false;
129129
parsed.err_msg_ = "Invalid character found (" + display_char(*p) + ") in path";
@@ -135,20 +135,22 @@ URI URI::Parse(std::string uri, URI::ParseOpts opts) {
135135
if (*p == '\0')
136136
return parsed;
137137

138-
// Query
139-
p++;
140-
parsed.query_start_ = p - p_start;
141-
while (*p != '\0' && *p != '#') {
142-
if (!allowed_char(*p) && !allow_non_escaped) {
143-
parsed.valid_ = false;
144-
parsed.err_msg_ = "Invalid character found (" + display_char(*p) + ") in query";
145-
return parsed;
146-
}
138+
if (*p == '?') {
139+
// Query
147140
p++;
141+
parsed.query_start_ = p - p_start;
142+
while (*p != '\0' && *p != '#') {
143+
if (!allowed_char(*p) && !allow_non_escaped) {
144+
parsed.valid_ = false;
145+
parsed.err_msg_ = "Invalid character found (" + display_char(*p) + ") in query";
146+
return parsed;
147+
}
148+
p++;
149+
}
150+
parsed.query_end_ = p - p_start;
151+
if (*p == '\0')
152+
return parsed;
148153
}
149-
parsed.query_end_ = p - p_start;
150-
if (*p == '\0')
151-
return parsed;
152154

153155
// Fragment
154156
p++;

dali/util/uri_test.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,56 @@ TEST(URI, Parse_7) {
9494
EXPECT_EQ("", uri.fragment());
9595
}
9696

97+
TEST(URI, Parse_FragmentWithoutAuthority) {
98+
auto uri = URI::Parse("urn:path#frag");
99+
EXPECT_EQ("urn", uri.scheme());
100+
EXPECT_EQ("", uri.authority());
101+
EXPECT_EQ("path", uri.path());
102+
EXPECT_EQ("", uri.query());
103+
EXPECT_EQ("path", uri.path_and_query());
104+
EXPECT_EQ("frag", uri.fragment());
105+
}
106+
107+
TEST(URI, Parse_FragmentWithoutQuery) {
108+
auto uri = URI::Parse("s3://bucket/path#fragment");
109+
EXPECT_EQ("s3", uri.scheme());
110+
EXPECT_EQ("bucket", uri.authority());
111+
EXPECT_EQ("/path", uri.path());
112+
EXPECT_EQ("", uri.query());
113+
EXPECT_EQ("/path", uri.path_and_query());
114+
EXPECT_EQ("fragment", uri.fragment());
115+
}
116+
117+
TEST(URI, Parse_EmptyQueryWithFragment) {
118+
auto uri = URI::Parse("s3://bucket/path?#fragment");
119+
EXPECT_EQ("s3", uri.scheme());
120+
EXPECT_EQ("bucket", uri.authority());
121+
EXPECT_EQ("/path", uri.path());
122+
EXPECT_EQ("", uri.query());
123+
EXPECT_EQ("/path?", uri.path_and_query());
124+
EXPECT_EQ("fragment", uri.fragment());
125+
}
126+
127+
TEST(URI, Parse_EmptyPathWithFragment) {
128+
auto uri = URI::Parse("s3://bucket#fragment");
129+
EXPECT_EQ("s3", uri.scheme());
130+
EXPECT_EQ("bucket", uri.authority());
131+
EXPECT_EQ("", uri.path());
132+
EXPECT_EQ("", uri.query());
133+
EXPECT_EQ("", uri.path_and_query());
134+
EXPECT_EQ("fragment", uri.fragment());
135+
}
136+
137+
TEST(URI, Parse_EmptyPathWithQueryAndFragment) {
138+
auto uri = URI::Parse("s3://bucket?query#fragment");
139+
EXPECT_EQ("s3", uri.scheme());
140+
EXPECT_EQ("bucket", uri.authority());
141+
EXPECT_EQ("", uri.path());
142+
EXPECT_EQ("query", uri.query());
143+
EXPECT_EQ("?query", uri.path_and_query());
144+
EXPECT_EQ("fragment", uri.fragment());
145+
}
146+
97147
TEST(URI, Parse_Error1) {
98148
auto uri = URI::Parse(
99149
"telnet://192. 0.2.16:80/");

0 commit comments

Comments
 (0)