Skip to content

Commit 374eeaf

Browse files
authored
Fixing #935 (#937)
1 parent 121c6a7 commit 374eeaf

File tree

3 files changed

+37
-16
lines changed

3 files changed

+37
-16
lines changed

src/helpers.cpp

+13-8
Original file line numberDiff line numberDiff line change
@@ -578,15 +578,20 @@ ada_really_inline void parse_prepared_path(std::string_view input,
578578
// Note: input cannot be empty, it must at least contain one character ('.')
579579
// Note: we know that '\' is not present.
580580
if (input[0] != '.') {
581-
size_t slashdot = input.find("/.");
582-
if (slashdot == std::string_view::npos) { // common case
583-
trivial_path = true;
584-
} else { // uncommon
585-
// only three cases matter: /./, /.. or a final /
586-
trivial_path =
587-
!(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
588-
input[slashdot + 2] == '/');
581+
size_t slashdot = 0;
582+
bool dot_is_file = true;
583+
for (;;) {
584+
slashdot = input.find("/.", slashdot);
585+
if (slashdot == std::string_view::npos) { // common case
586+
break;
587+
} else { // uncommon
588+
// only three cases matter: /./, /.. or a final /
589+
slashdot += 2;
590+
dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
591+
input[slashdot] == '/');
592+
}
589593
}
594+
trivial_path = dot_is_file;
590595
}
591596
}
592597
if (trivial_path) {

src/url_aggregator.cpp

+13-8
Original file line numberDiff line numberDiff line change
@@ -1412,15 +1412,20 @@ inline void url_aggregator::consume_prepared_path(std::string_view input) {
14121412
// Note: input cannot be empty, it must at least contain one character ('.')
14131413
// Note: we know that '\' is not present.
14141414
if (input[0] != '.') {
1415-
size_t slashdot = input.find("/.");
1416-
if (slashdot == std::string_view::npos) { // common case
1417-
trivial_path = true;
1418-
} else { // uncommon
1419-
// only three cases matter: /./, /.. or a final /
1420-
trivial_path =
1421-
!(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
1422-
input[slashdot + 2] == '/');
1415+
size_t slashdot = 0;
1416+
bool dot_is_file = true;
1417+
for (;;) {
1418+
slashdot = input.find("/.", slashdot);
1419+
if (slashdot == std::string_view::npos) { // common case
1420+
break;
1421+
} else { // uncommon
1422+
// only three cases matter: /./, /.. or a final /
1423+
slashdot += 2;
1424+
dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
1425+
input[slashdot] == '/');
1426+
}
14231427
}
1428+
trivial_path = dot_is_file;
14241429
}
14251430
}
14261431
if (trivial_path && is_at_path()) {

tests/basic_tests.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,14 @@ TYPED_TEST(basic_tests, test_possible_asan) {
505505
ASSERT_EQ(url->get_protocol(), "file:");
506506
SUCCEED();
507507
}
508+
509+
TYPED_TEST(basic_tests, test_issue_935) {
510+
auto url = ada::parse<TypeParam>("file:///foo/.bar/../baz.js");
511+
ASSERT_TRUE(url);
512+
ASSERT_EQ(url->get_pathname(), "/foo/baz.js");
513+
514+
// this should go into the fast path also
515+
auto no_dot = ada::parse<TypeParam>("file:///foo/bar/baz.js");
516+
ASSERT_EQ(no_dot->get_pathname(), "/foo/bar/baz.js");
517+
SUCCEED();
518+
}

0 commit comments

Comments
 (0)