Skip to content

Commit d4ab1a6

Browse files
authored
verifies and fixes issue 50235 in node. (#540)
1 parent 11731e8 commit d4ab1a6

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

include/ada/url_aggregator-inl.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -817,20 +817,31 @@ inline bool url_aggregator::has_port() const noexcept {
817817
// is greater than 1, and url's path[0] is the empty string, then append
818818
// U+002F (/) followed by U+002E (.) to output.
819819
ada_log("url_aggregator::has_dash_dot");
820-
// Performance: instead of doing this potentially expensive check, we could
821-
// just have a boolean value in the structure.
822820
#if ADA_DEVELOPMENT_CHECKS
823-
if (components.pathname_start + 1 < buffer.size() &&
824-
components.pathname_start == components.host_end + 2) {
825-
ADA_ASSERT_TRUE(buffer[components.host_end] == '/');
826-
ADA_ASSERT_TRUE(buffer[components.host_end + 1] == '.');
821+
// If pathname_start and host_end are exactly two characters apart, then we
822+
// either have a one-digit port such as http://test.com:5?param=1 or else we
823+
// have a /.: sequence such as "non-spec:/.//". We test that this is the case.
824+
if (components.pathname_start == components.host_end + 2) {
825+
ADA_ASSERT_TRUE((buffer[components.host_end] == '/' &&
826+
buffer[components.host_end + 1] == '.') ||
827+
(buffer[components.host_end] == ':' &&
828+
checkers::is_digit(buffer[components.host_end + 1])));
829+
}
830+
if (components.pathname_start == components.host_end + 2 &&
831+
buffer[components.host_end] == '/' &&
832+
buffer[components.host_end + 1] == '.') {
833+
ADA_ASSERT_TRUE(components.pathname_start + 1 < buffer.size());
827834
ADA_ASSERT_TRUE(buffer[components.pathname_start] == '/');
828835
ADA_ASSERT_TRUE(buffer[components.pathname_start + 1] == '/');
829836
}
830837
#endif
831-
return !has_opaque_path &&
832-
components.pathname_start == components.host_end + 2 &&
833-
components.pathname_start + 1 < buffer.size();
838+
// Performance: it should be uncommon for components.pathname_start ==
839+
// components.host_end + 2 to be true. So we put this check first in the
840+
// sequence. Most times, we do not have an opaque path. Checking for '/.' is
841+
// more expensive, but should be uncommon.
842+
return components.pathname_start == components.host_end + 2 &&
843+
!has_opaque_path && buffer[components.host_end] == '/' &&
844+
buffer[components.host_end + 1] == '.';
834845
}
835846

836847
[[nodiscard]] inline std::string_view url_aggregator::get_href()

tests/basic_tests.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,3 +387,12 @@ TYPED_TEST(basic_tests, nodejs_49650) {
387387
ASSERT_EQ(out->get_href(), "http://foo/");
388388
SUCCEED();
389389
}
390+
391+
// https://github.com/nodejs/node/issues/50235
392+
TYPED_TEST(basic_tests, nodejs_50235) {
393+
auto out = ada::parse<TypeParam>("http://test.com:5/?param=1");
394+
ASSERT_TRUE(out);
395+
ASSERT_TRUE(out->set_pathname("path"));
396+
ASSERT_EQ(out->get_href(), "http://test.com:5/path?param=1");
397+
SUCCEED();
398+
}

0 commit comments

Comments
 (0)