| Index: third_party/WebKit/Source/core/frame/History.cpp
|
| diff --git a/third_party/WebKit/Source/core/frame/History.cpp b/third_party/WebKit/Source/core/frame/History.cpp
|
| index 30ebcc037c8ef77fc46f2cb63e954175ea56360a..a9cfa0fe790ecec6a4a9257bbb880d45c56476e2 100644
|
| --- a/third_party/WebKit/Source/core/frame/History.cpp
|
| +++ b/third_party/WebKit/Source/core/frame/History.cpp
|
| @@ -38,6 +38,8 @@
|
| #include "platform/bindings/ScriptState.h"
|
| #include "platform/weborigin/KURL.h"
|
| #include "platform/weborigin/SecurityOrigin.h"
|
| +#include "platform/wtf/CurrentTime.h"
|
| +#include "platform/wtf/HashMap.h"
|
| #include "platform/wtf/text/StringView.h"
|
|
|
| namespace blink {
|
| @@ -116,6 +118,26 @@ HistoryScrollRestorationType History::ScrollRestorationInternal() const {
|
| : kScrollRestorationAuto;
|
| }
|
|
|
| +// TODO(crbug.com/394296): This is not the long-term fix to IPC flooding that we
|
| +// need. However, it does mitigate the immediate concern of |pushState| DoS
|
| +// (assuming the renderer has not been compromised).
|
| +bool History::IsHostFloodingPushState(const String& hostname) const {
|
| + const int kHostPushStateLimit = 50;
|
| + const HostLimit& current = host_limits.at(hostname);
|
| +
|
| + if (current.first > kHostPushStateLimit) {
|
| + const double kHostPushStateLimitResetSeconds = 10.0;
|
| + double now = MonotonicallyIncreasingTime();
|
| + if (now - current.second > kHostPushStateLimitResetSeconds) {
|
| + host_limits.Set(hostname, HostLimit{0, now});
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + host_limits.Set(hostname, HostLimit{current.first + 1, current.second});
|
| + return false;
|
| +}
|
| +
|
| bool History::stateChanged() const {
|
| return last_state_object_requested_ != StateInternal();
|
| }
|
| @@ -216,6 +238,11 @@ void History::StateObjectAdded(PassRefPtr<SerializedScriptValue> data,
|
| !GetFrame()->Loader().GetDocumentLoader())
|
| return;
|
|
|
| + if (IsHostFloodingPushState(
|
| + GetFrame()->GetDocument()->GetSecurityOrigin()->Host())) {
|
| + return;
|
| + }
|
| +
|
| KURL full_url = UrlForState(url_string);
|
| if (!CanChangeToUrl(full_url, GetFrame()->GetDocument()->GetSecurityOrigin(),
|
| GetFrame()->GetDocument()->Url())) {
|
|
|