From bfe0df56777b7c6f2c929390baad4c9a547c4269 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 4 Mar 2023 22:37:12 +0000 Subject: [PATCH] LibWeb/HTML: Add missing SecurityError checks to Location --- Userland/Libraries/LibWeb/HTML/Location.cpp | 62 ++++++++++++++++----- Userland/Libraries/LibWeb/HTML/Location.h | 2 +- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/Userland/Libraries/LibWeb/HTML/Location.cpp b/Userland/Libraries/LibWeb/HTML/Location.cpp index 6c6149c2b72..1ff44e4e246 100644 --- a/Userland/Libraries/LibWeb/HTML/Location.cpp +++ b/Userland/Libraries/LibWeb/HTML/Location.cpp @@ -51,7 +51,7 @@ JS::ThrowCompletionOr Location::initialize(JS::Realm& realm) } // https://html.spec.whatwg.org/multipage/history.html#relevant-document -DOM::Document const* Location::relevant_document() const +JS::GCPtr Location::relevant_document() const { // A Location object has an associated relevant Document, which is this Location object's // relevant global object's browsing context's active document, if this Location object's @@ -65,7 +65,7 @@ AK::URL Location::url() const { // A Location object has an associated url, which is this Location object's relevant Document's URL, // if this Location object's relevant Document is non-null, and about:blank otherwise. - auto const* relevant_document = this->relevant_document(); + auto const relevant_document = this->relevant_document(); return relevant_document ? relevant_document->url() : "about:blank"sv; } @@ -74,7 +74,10 @@ WebIDL::ExceptionOr Location::href() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); // 2. Return this's url, serialized. return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(url().serialize())); @@ -86,7 +89,10 @@ WebIDL::ExceptionOr Location::set_href(String const& new_href) auto& vm = this->vm(); auto& window = verify_cast(HTML::current_global_object()); - // FIXME: 1. If this's relevant Document is null, then return. + // 1. If this's relevant Document is null, then return. + auto const relevant_document = this->relevant_document(); + if (!relevant_document) + return {}; // 2. Parse the given value relative to the entry settings object. If that failed, throw a TypeError exception. auto href_url = window.associated_document().parse_url(new_href.to_deprecated_string()); @@ -104,7 +110,10 @@ WebIDL::ExceptionOr Location::origin() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); // 2. Return the serialization of this's url's origin. return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(url().serialize_origin())); @@ -115,7 +124,10 @@ WebIDL::ExceptionOr Location::protocol() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); // 2. Return this's url's scheme, followed by ":". return TRY_OR_THROW_OOM(vm, String::formatted("{}:", url().scheme())); @@ -132,7 +144,10 @@ WebIDL::ExceptionOr Location::host() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); // 2. Let url be this's url. auto url = this->url(); @@ -160,7 +175,10 @@ WebIDL::ExceptionOr Location::hostname() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); auto url = this->url(); @@ -183,7 +201,10 @@ WebIDL::ExceptionOr Location::port() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); auto url = this->url(); @@ -206,7 +227,10 @@ WebIDL::ExceptionOr Location::pathname() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); // 2. Return the result of URL path serializing this Location object's url. return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(url().path())); @@ -223,7 +247,10 @@ WebIDL::ExceptionOr Location::search() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); auto url = this->url(); @@ -246,7 +273,10 @@ WebIDL::ExceptionOr Location::hash() const { auto& vm = this->vm(); - // FIXME: 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 1. If this's relevant Document is non-null and its origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + auto const relevant_document = this->relevant_document(); + if (relevant_document && !relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); auto url = this->url(); @@ -262,11 +292,15 @@ WebIDL::ExceptionOr Location::hash() const WebIDL::ExceptionOr Location::set_hash(String const& value) { // The hash setter steps are: + auto const relevant_document = this->relevant_document(); + // 1. If this's relevant Document is null, then return. - if (!relevant_document()) + if (!relevant_document) return {}; - // FIXME: 2. If this's relevant Document's origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + // 2. If this's relevant Document's origin is not same origin-domain with the entry settings object's origin, then throw a "SecurityError" DOMException. + if (!relevant_document->origin().is_same_origin_domain(entry_settings_object().origin())) + return WebIDL::SecurityError::create(realm(), "Location's relevant document is not same origin-domain with the entry settings object's origin"sv); // 3. Let copyURL be a copy of this's url. auto copy_url = this->url(); diff --git a/Userland/Libraries/LibWeb/HTML/Location.h b/Userland/Libraries/LibWeb/HTML/Location.h index 9ba033f23a7..5ea4493e8ba 100644 --- a/Userland/Libraries/LibWeb/HTML/Location.h +++ b/Userland/Libraries/LibWeb/HTML/Location.h @@ -71,7 +71,7 @@ private: virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; - DOM::Document const* relevant_document() const; + JS::GCPtr relevant_document() const; AK::URL url() const; // [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap