Skip to content

Commit a094ace

Browse files
committed
fix(url): handle :port values in host setter
1 parent 392d4b7 commit a094ace

File tree

3 files changed

+120
-46
lines changed

3 files changed

+120
-46
lines changed

src/url.cpp

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -691,35 +691,67 @@ bool url::set_host_or_hostname(const std::string_view input) {
691691
// Note: the 'found_colon' value is true if and only if a colon was
692692
// encountered while not inside brackets.
693693
if (found_colon) {
694+
// If buffer is the empty string, host-missing validation error, return
695+
// failure.
696+
std::string_view buffer = host_view.substr(0, location);
697+
if (buffer.empty()) {
698+
return false;
699+
}
700+
701+
// If state override is given and state override is hostname state, then
702+
// return failure.
694703
if constexpr (override_hostname) {
695704
return false;
696705
}
697-
std::string_view buffer = new_host.substr(location + 1);
698-
if (!buffer.empty()) {
699-
set_port(buffer);
706+
707+
// Let host be the result of host parsing buffer with url is not special.
708+
bool succeeded = parse_host(buffer);
709+
if (!succeeded) {
710+
host = std::move(previous_host);
711+
update_base_port(previous_port);
712+
return false;
700713
}
701-
}
702-
// If url is special and host_view is the empty string, validation error,
703-
// return failure. Otherwise, if state override is given, host_view is the
704-
// empty string, and either url includes credentials or url's port is
705-
// non-null, return.
706-
else if (host_view.empty() &&
707-
(is_special() || has_credentials() || port.has_value())) {
708-
return false;
709-
}
710714

711-
// Let host be the result of host parsing host_view with url is not special.
712-
if (host_view.empty() && !is_special()) {
713-
host = "";
715+
// Set url's host to host, buffer to the empty string, and state to port
716+
// state.
717+
std::string_view port_buffer = new_host.substr(location + 1);
718+
if (!port_buffer.empty()) {
719+
set_port(port_buffer);
720+
}
714721
return true;
715722
}
723+
// Otherwise, if one of the following is true:
724+
// - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
725+
// - url is special and c is U+005C (\)
726+
else {
727+
// If url is special and host_view is the empty string, host-missing
728+
// validation error, return failure.
729+
if (host_view.empty() && is_special()) {
730+
return false;
731+
}
716732

717-
bool succeeded = parse_host(host_view);
718-
if (!succeeded) {
719-
host = std::move(previous_host);
720-
update_base_port(previous_port);
733+
// Otherwise, if state override is given, host_view is the empty string,
734+
// and either url includes credentials or url's port is non-null, then
735+
// return failure.
736+
if (host_view.empty() && (has_credentials() || port.has_value())) {
737+
return false;
738+
}
739+
740+
// Let host be the result of host parsing host_view with url is not
741+
// special.
742+
if (host_view.empty() && !is_special()) {
743+
host = "";
744+
return true;
745+
}
746+
747+
bool succeeded = parse_host(host_view);
748+
if (!succeeded) {
749+
host = std::move(previous_host);
750+
update_base_port(previous_port);
751+
return false;
752+
}
753+
return true;
721754
}
722-
return succeeded;
723755
}
724756

725757
size_t location = new_host.find_first_of("/\\?");

src/url_aggregator.cpp

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -549,43 +549,75 @@ bool url_aggregator::set_host_or_hostname(const std::string_view input) {
549549
// Note: the 'found_colon' value is true if and only if a colon was
550550
// encountered while not inside brackets.
551551
if (found_colon) {
552+
// If buffer is the empty string, host-missing validation error, return
553+
// failure.
554+
std::string_view host_buffer = host_view.substr(0, location);
555+
if (host_buffer.empty()) {
556+
return false;
557+
}
558+
559+
// If state override is given and state override is hostname state, then
560+
// return failure.
552561
if constexpr (override_hostname) {
553562
return false;
554563
}
555-
std::string_view sub_buffer = new_host.substr(location + 1);
556-
if (!sub_buffer.empty()) {
557-
set_port(sub_buffer);
564+
565+
// Let host be the result of host parsing buffer with url is not special.
566+
bool succeeded = parse_host(host_buffer);
567+
if (!succeeded) {
568+
update_base_hostname(previous_host);
569+
update_base_port(previous_port);
570+
return false;
558571
}
572+
573+
// Set url's host to host, buffer to the empty string, and state to port
574+
// state.
575+
std::string_view port_buffer = new_host.substr(location + 1);
576+
if (!port_buffer.empty()) {
577+
set_port(port_buffer);
578+
}
579+
return true;
559580
}
560-
// If url is special and host_view is the empty string, validation error,
561-
// return failure. Otherwise, if state override is given, host_view is the
562-
// empty string, and either url includes credentials or url's port is
563-
// non-null, return.
564-
else if (host_view.empty() &&
565-
(is_special() || has_credentials() || has_port())) {
566-
return false;
567-
}
581+
// Otherwise, if one of the following is true:
582+
// - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
583+
// - url is special and c is U+005C (\)
584+
else {
585+
// If url is special and host_view is the empty string, host-missing
586+
// validation error, return failure.
587+
if (host_view.empty() && is_special()) {
588+
return false;
589+
}
568590

569-
// Let host be the result of host parsing host_view with url is not special.
570-
if (host_view.empty() && !is_special()) {
571-
if (has_hostname()) {
572-
clear_hostname(); // easy!
591+
// Otherwise, if state override is given, host_view is the empty string,
592+
// and either url includes credentials or url's port is non-null, then
593+
// return failure.
594+
if (host_view.empty() && (has_credentials() || has_port())) {
595+
return false;
596+
}
597+
598+
// Let host be the result of host parsing host_view with url is not
599+
// special.
600+
if (host_view.empty() && !is_special()) {
601+
if (has_hostname()) {
602+
clear_hostname(); // easy!
603+
} else if (has_dash_dot()) {
604+
add_authority_slashes_if_needed();
605+
delete_dash_dot();
606+
}
607+
return true;
608+
}
609+
610+
bool succeeded = parse_host(host_view);
611+
if (!succeeded) {
612+
update_base_hostname(previous_host);
613+
update_base_port(previous_port);
614+
return false;
573615
} else if (has_dash_dot()) {
574-
add_authority_slashes_if_needed();
616+
// Should remove dash_dot from pathname
575617
delete_dash_dot();
576618
}
577619
return true;
578620
}
579-
580-
bool succeeded = parse_host(host_view);
581-
if (!succeeded) {
582-
update_base_hostname(previous_host);
583-
update_base_port(previous_port);
584-
} else if (has_dash_dot()) {
585-
// Should remove dash_dot from pathname
586-
delete_dash_dot();
587-
}
588-
return succeeded;
589621
}
590622

591623
size_t location = new_host.find_first_of("/\\?");

tests/wpt/ada_extra_setters_tests.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,15 @@
144144
"pathname": "space %20"
145145
}
146146
}
147+
],
148+
"host": [
149+
{
150+
"href": "foo://path/to",
151+
"new_value": ":80",
152+
"expected": {
153+
"href": "foo://path/to",
154+
"host": "path"
155+
}
156+
}
147157
]
148158
}

0 commit comments

Comments
 (0)