Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Unified Diff: content/browser/frame_host/navigation_handle_impl.cc

Issue 2528813002: Fix Self-Referencing OOPIF Infinite Loop (Closed)
Patch Set: make EqualIgnoringFragmentIdentifier more efficient Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/frame_host/navigation_handle_impl.cc
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index fda35af58e877586b5736f89e81dd4ea45c01606..b9cdeb6bf4a57287e75248d8fedbaf9f2df5435a 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -54,6 +54,33 @@ void NotifyAbandonedTransferNavigation(const GlobalRequestID& id) {
rdh->CancelRequest(id.child_id, id.request_id);
}
+// This is a helper method used in IsSelfReferentialURL. It checks if two
+// URLs are identical when the URL fragments are removed.
+bool EqualIgnoringFragmentIdentifier(const GURL& a, const GURL& b) {
nasko 2017/02/07 19:51:20 This is actually being implemented in GURL itself
davidsac (gone - try alexmos) 2017/02/10 18:44:26 Acknowledged.
+ // Compute the length of each URL without its ref. Note that the reference
+ // begin (if it exists) points to the character *after* the '#', so we need
+ // to subtract one.
+ int aLength = a.spec().length();
+ if (a.parsed_for_possibly_invalid_spec().ref.len >= 0)
+ aLength = a.parsed_for_possibly_invalid_spec().ref.begin - 1;
+
+ int bLength = b.spec().length();
+ if (b.parsed_for_possibly_invalid_spec().ref.len >= 0)
+ bLength = b.parsed_for_possibly_invalid_spec().ref.begin - 1;
+
+ if (aLength != bLength)
+ return false;
+
+ const std::string& aString = a.spec();
+ const std::string& bString = b.spec();
+ // FIXME: Abstraction this into a function in WTFString.h.
+ for (int i = 0; i < aLength; ++i) {
+ if (aString[i] != bString[i])
+ return false;
+ }
+ return true;
+}
+
} // namespace
// static
@@ -507,6 +534,12 @@ void NavigationHandleImpl::WillStartRequest(
state_ = WILL_SEND_REQUEST;
complete_callback_ = callback;
+ if (IsSelfReferentialURL()) {
+ state_ = CANCELING;
+ RunCompleteCallback(NavigationThrottle::CANCEL);
+ return;
+ }
+
RegisterNavigationThrottles();
if (IsBrowserSideNavigationEnabled())
@@ -549,6 +582,12 @@ void NavigationHandleImpl::WillRedirectRequest(
state_ = WILL_REDIRECT_REQUEST;
complete_callback_ = callback;
+ if (IsSelfReferentialURL()) {
+ state_ = CANCELING;
+ RunCompleteCallback(NavigationThrottle::CANCEL);
+ return;
+ }
+
// Notify each throttle of the request.
NavigationThrottle::ThrottleCheckResult result = CheckWillRedirectRequest();
@@ -885,4 +924,29 @@ void NavigationHandleImpl::RegisterNavigationThrottles() {
std::make_move_iterator(throttles_to_register.end()));
}
+bool NavigationHandleImpl::IsSelfReferentialURL() {
+ // about: URLs should be exempted since they are reserved for other purposes
+ // and cannot be the source of infinite recursion. See
+ // https://crbug.com/341858 .
+ if (url_.SchemeIs("about"))
+ return false;
+
+ // Browser-triggered navigations should be exempted.
+ if (!is_renderer_initiated_)
+ return false;
+
+ // We allow one level of self-reference because some sites depend on that,
+ // but we don't allow more than one.
+ bool found_self_reference = false;
+ for (const FrameTreeNode* node = frame_tree_node_->parent(); node;
+ node = node->parent()) {
+ if (EqualIgnoringFragmentIdentifier(node->current_url(), url_)) {
+ if (found_self_reference)
+ return true;
+ found_self_reference = true;
+ }
+ }
+ return false;
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698