<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[248577] branches/safari-608-branch</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/248577">248577</a></dd>
<dt>Author</dt> <dd>alancoon@apple.com</dd>
<dt>Date</dt> <dd>2019-08-12 16:42:48 -0700 (Mon, 12 Aug 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Cherry-pick <a href="http://trac.webkit.org/projects/webkit/changeset/248494">r248494</a>. rdar://problem/54171876

    Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive
    https://bugs.webkit.org/show_bug.cgi?id=199864

    Reviewed by Saam Barati.

    Source/JavaScriptCore:

    Our JSObject::put implementation is not correct in term of the spec. Our [[Put]] implementation is something like this.

        JSObject::put(object):
            if (can-do-fast-path(object))
                return fast-path(object);
            // slow-path
            do {
                object-put-check-and-setter-calls(object); // (1)
                object = object->prototype;
            } while (is-object(object));
            return do-put(object);

    Since JSObject::put is registered in the methodTable, the derived classes can override it. Some of classes are adding
    extra checks to this put.

        Derived::put(object):
            if (do-extra-check(object))
                fail
            return JSObject::put(object)

    The problem is that Derived::put is only called when the |this| object is the Derived class. When traversing [[Prototype]] in
    JSObject::put, at (1), we do not perform the extra checks added in Derived::put even if `object` is Derived one. This means that
    we skip the check.

    Currently, JSObject::put and WebCore checking mechanism are broken. JSObject::put should call getOwnPropertySlot at (1) to
    perform the additional checks. This behavior is matching against the spec. However, currently, our JSObject::getOwnPropertySlot
    does not propagate setter information. This is required to cache cacheable [[Put]] at (1) for CustomValue, CustomAccessor, and
    Accessors. We also need to reconsider how to integrate static property setters to this mechanism. So, basically, this involves
    large refactoring to renew our JSObject::put and JSObject::getOwnPropertySlot.

    To work-around for now, we add a new TypeInfo flag, HasPutPropertySecurityCheck . And adding this flag to DOM objects
    that implements the addition checks. We also add doPutPropertySecurityCheck method hook to perform the check in JSObject.
    When we found this flag at (1), we perform doPutPropertySecurityCheck to properly perform the checks.

    Since our JSObject::put code is old and it does not match against the spec now, we should refactor it largely. This is tracked separately in [1].

    [1]: https://bugs.webkit.org/show_bug.cgi?id=200562

    * runtime/ClassInfo.h:
    * runtime/JSCJSValue.cpp:
    (JSC::JSValue::putToPrimitive):
    * runtime/JSCell.cpp:
    (JSC::JSCell::doPutPropertySecurityCheck):
    * runtime/JSCell.h:
    * runtime/JSObject.cpp:
    (JSC::JSObject::putInlineSlow):
    (JSC::JSObject::getOwnPropertyDescriptor):
    * runtime/JSObject.h:
    (JSC::JSObject::doPutPropertySecurityCheck):
    * runtime/JSTypeInfo.h:
    (JSC::TypeInfo::hasPutPropertySecurityCheck const):

    Source/WebCore:

    Test: http/tests/security/cross-frame-access-object-put-optimization.html

    * bindings/js/JSDOMWindowCustom.cpp:
    (WebCore::JSDOMWindow::doPutPropertySecurityCheck):
    * bindings/js/JSLocationCustom.cpp:
    (WebCore::JSLocation::doPutPropertySecurityCheck):
    * bindings/scripts/CodeGeneratorJS.pm:
    (GenerateHeader):
    * bindings/scripts/test/JS/JSTestActiveDOMObject.h:

    LayoutTests:

    * http/tests/security/cross-frame-access-object-put-optimization-expected.txt: Added.
    * http/tests/security/cross-frame-access-object-put-optimization.html: Added.
    * http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html: Added.

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248494 268f45cc-cd09-0410-ab3c-d52691b4dbfc</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari608branchLayoutTestsChangeLog">branches/safari-608-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreChangeLog">branches/safari-608-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreruntimeClassInfoh">branches/safari-608-branch/Source/JavaScriptCore/runtime/ClassInfo.h</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreruntimeJSCJSValuecpp">branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCJSValue.cpp</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreruntimeJSCellcpp">branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.cpp</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreruntimeJSCellh">branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.h</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreruntimeJSObjectcpp">branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.cpp</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreruntimeJSObjecth">branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#branchessafari608branchSourceJavaScriptCoreruntimeJSTypeInfoh">branches/safari-608-branch/Source/JavaScriptCore/runtime/JSTypeInfo.h</a></li>
<li><a href="#branchessafari608branchSourceWebCoreChangeLog">branches/safari-608-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari608branchSourceWebCorebindingsjsJSDOMWindowCustomcpp">branches/safari-608-branch/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp</a></li>
<li><a href="#branchessafari608branchSourceWebCorebindingsjsJSLocationCustomcpp">branches/safari-608-branch/Source/WebCore/bindings/js/JSLocationCustom.cpp</a></li>
<li><a href="#branchessafari608branchSourceWebCorebindingsscriptsCodeGeneratorJSpm">branches/safari-608-branch/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#branchessafari608branchSourceWebCorebindingsscriptstestJSJSTestActiveDOMObjecth">branches/safari-608-branch/Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari608branchLayoutTestshttptestssecuritycrossframeaccessobjectputoptimizationexpectedtxt">branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization-expected.txt</a></li>
<li><a href="#branchessafari608branchLayoutTestshttptestssecuritycrossframeaccessobjectputoptimizationhtml">branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization.html</a></li>
<li><a href="#branchessafari608branchLayoutTestshttptestssecurityresourcescrossframeiframeforobjectputoptimizationtesthtml">branches/safari-608-branch/LayoutTests/http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari608branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/LayoutTests/ChangeLog (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/LayoutTests/ChangeLog 2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/LayoutTests/ChangeLog    2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -1,5 +1,99 @@
</span><span class="cx"> 2019-08-12  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><ins>+        Cherry-pick r248494. rdar://problem/54171876
+
+    Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive
+    https://bugs.webkit.org/show_bug.cgi?id=199864
+    
+    Reviewed by Saam Barati.
+    
+    Source/JavaScriptCore:
+    
+    Our JSObject::put implementation is not correct in term of the spec. Our [[Put]] implementation is something like this.
+    
+        JSObject::put(object):
+            if (can-do-fast-path(object))
+                return fast-path(object);
+            // slow-path
+            do {
+                object-put-check-and-setter-calls(object); // (1)
+                object = object->prototype;
+            } while (is-object(object));
+            return do-put(object);
+    
+    Since JSObject::put is registered in the methodTable, the derived classes can override it. Some of classes are adding
+    extra checks to this put.
+    
+        Derived::put(object):
+            if (do-extra-check(object))
+                fail
+            return JSObject::put(object)
+    
+    The problem is that Derived::put is only called when the |this| object is the Derived class. When traversing [[Prototype]] in
+    JSObject::put, at (1), we do not perform the extra checks added in Derived::put even if `object` is Derived one. This means that
+    we skip the check.
+    
+    Currently, JSObject::put and WebCore checking mechanism are broken. JSObject::put should call getOwnPropertySlot at (1) to
+    perform the additional checks. This behavior is matching against the spec. However, currently, our JSObject::getOwnPropertySlot
+    does not propagate setter information. This is required to cache cacheable [[Put]] at (1) for CustomValue, CustomAccessor, and
+    Accessors. We also need to reconsider how to integrate static property setters to this mechanism. So, basically, this involves
+    large refactoring to renew our JSObject::put and JSObject::getOwnPropertySlot.
+    
+    To work-around for now, we add a new TypeInfo flag, HasPutPropertySecurityCheck . And adding this flag to DOM objects
+    that implements the addition checks. We also add doPutPropertySecurityCheck method hook to perform the check in JSObject.
+    When we found this flag at (1), we perform doPutPropertySecurityCheck to properly perform the checks.
+    
+    Since our JSObject::put code is old and it does not match against the spec now, we should refactor it largely. This is tracked separately in [1].
+    
+    [1]: https://bugs.webkit.org/show_bug.cgi?id=200562
+    
+    * runtime/ClassInfo.h:
+    * runtime/JSCJSValue.cpp:
+    (JSC::JSValue::putToPrimitive):
+    * runtime/JSCell.cpp:
+    (JSC::JSCell::doPutPropertySecurityCheck):
+    * runtime/JSCell.h:
+    * runtime/JSObject.cpp:
+    (JSC::JSObject::putInlineSlow):
+    (JSC::JSObject::getOwnPropertyDescriptor):
+    * runtime/JSObject.h:
+    (JSC::JSObject::doPutPropertySecurityCheck):
+    * runtime/JSTypeInfo.h:
+    (JSC::TypeInfo::hasPutPropertySecurityCheck const):
+    
+    Source/WebCore:
+    
+    Test: http/tests/security/cross-frame-access-object-put-optimization.html
+    
+    * bindings/js/JSDOMWindowCustom.cpp:
+    (WebCore::JSDOMWindow::doPutPropertySecurityCheck):
+    * bindings/js/JSLocationCustom.cpp:
+    (WebCore::JSLocation::doPutPropertySecurityCheck):
+    * bindings/scripts/CodeGeneratorJS.pm:
+    (GenerateHeader):
+    * bindings/scripts/test/JS/JSTestActiveDOMObject.h:
+    
+    LayoutTests:
+    
+    * http/tests/security/cross-frame-access-object-put-optimization-expected.txt: Added.
+    * http/tests/security/cross-frame-access-object-put-optimization.html: Added.
+    * http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html: Added.
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248494 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2019-08-09  Yusuke Suzuki  <ysuzuki@apple.com>
+
+            Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive
+            https://bugs.webkit.org/show_bug.cgi?id=199864
+
+            Reviewed by Saam Barati.
+
+            * http/tests/security/cross-frame-access-object-put-optimization-expected.txt: Added.
+            * http/tests/security/cross-frame-access-object-put-optimization.html: Added.
+            * http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html: Added.
+
+2019-08-12  Alan Coon  <alancoon@apple.com>
+
</ins><span class="cx">         Cherry-pick r248491. rdar://problem/54130636
</span><span class="cx"> 
</span><span class="cx">     Don't allow cross-origin iframes to autofocus
</span></span></pre></div>
<a id="branchessafari608branchLayoutTestshttptestssecuritycrossframeaccessobjectputoptimizationexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization-expected.txt (0 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization-expected.txt                               (rev 0)
+++ branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization-expected.txt  2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+This tests that you can't get cross-origin object during [[Put]] operation.
+
+PASS data is not "null"
+PASS data is not "Cocoa"
+PASS data is not "null"
+PASS data is not "Cocoa"
+PASS: successfullyParsed should be 'true' and is.
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="branchessafari608branchLayoutTestshttptestssecuritycrossframeaccessobjectputoptimizationhtml"></a>
<div class="addfile"><h4>Added: branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization.html (0 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization.html                               (rev 0)
+++ branches/safari-608-branch/LayoutTests/http/tests/security/cross-frame-access-object-put-optimization.html  2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+<html>
+<head>
+    <script src="/js-test-resources/js-test-pre.js"></script>
+    <script src="resources/cross-frame-access.js"></script>
+    <script>
+        jsTestIsAsync = true;
+
+        data = null;
+
+        // Set up listener for message from iframe
+        addEventListener('message', function(event) {
+            if (event.data == "finishedLoad")
+                doTest();
+        }, false);
+
+        function turnLeakedException(object) {
+            try {
+                object.setter = {toString: function() { return {} } };
+            } catch (e) {
+                let crossOriginFunctionConstructor = e.constructor.constructor;
+                data = crossOriginFunctionConstructor(`
+                    var element = document.getElementById("password");
+                    if (!element)
+                        return null;
+                    return element.textContent;`)();
+            }
+            shouldNotBeEqualToString(`data`, `null`);
+            shouldNotBeEqualToString(`data`, "Cocoa");
+            data = null;
+        }
+
+        doTest = function()
+        {
+            let targetWindow = document.getElementById("target").contentWindow;
+
+            // putInlineSlow
+            turnLeakedException({__proto__: targetWindow.location});
+
+            // putToPrimitive
+            num = 1337;
+            num.__proto__.__proto__ = targetWindow.location;
+            turnLeakedException(num);
+
+            finishJSTest();
+        }
+    </script>
+</head>
+<body>
+    <div>This tests that you can't get cross-origin object during [[Put]] operation.</div>
+    <iframe id="target" src="http://localhost:8000/security/resources/cross-frame-iframe-for-object-put-optimization-test.html"></iframe>
+    <pre id="console"></pre>
+    <script src="/js-test-resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari608branchLayoutTestshttptestssecurityresourcescrossframeiframeforobjectputoptimizationtesthtml"></a>
<div class="addfile"><h4>Added: branches/safari-608-branch/LayoutTests/http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html (0 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/LayoutTests/http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html                            (rev 0)
+++ branches/safari-608-branch/LayoutTests/http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html       2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+<h1 id="password">Cocoa</h1>
+<script>
+onload = function() {
+    location.__defineSetter__('setter', function(value) {
+        throw new Error();
+    });
+    parent.postMessage("finishedLoad", "*");
+}
+</script>
</ins></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/ChangeLog (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/ChangeLog       2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/ChangeLog  2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -1,5 +1,147 @@
</span><span class="cx"> 2019-08-12  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><ins>+        Cherry-pick r248494. rdar://problem/54171876
+
+    Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive
+    https://bugs.webkit.org/show_bug.cgi?id=199864
+    
+    Reviewed by Saam Barati.
+    
+    Source/JavaScriptCore:
+    
+    Our JSObject::put implementation is not correct in term of the spec. Our [[Put]] implementation is something like this.
+    
+        JSObject::put(object):
+            if (can-do-fast-path(object))
+                return fast-path(object);
+            // slow-path
+            do {
+                object-put-check-and-setter-calls(object); // (1)
+                object = object->prototype;
+            } while (is-object(object));
+            return do-put(object);
+    
+    Since JSObject::put is registered in the methodTable, the derived classes can override it. Some of classes are adding
+    extra checks to this put.
+    
+        Derived::put(object):
+            if (do-extra-check(object))
+                fail
+            return JSObject::put(object)
+    
+    The problem is that Derived::put is only called when the |this| object is the Derived class. When traversing [[Prototype]] in
+    JSObject::put, at (1), we do not perform the extra checks added in Derived::put even if `object` is Derived one. This means that
+    we skip the check.
+    
+    Currently, JSObject::put and WebCore checking mechanism are broken. JSObject::put should call getOwnPropertySlot at (1) to
+    perform the additional checks. This behavior is matching against the spec. However, currently, our JSObject::getOwnPropertySlot
+    does not propagate setter information. This is required to cache cacheable [[Put]] at (1) for CustomValue, CustomAccessor, and
+    Accessors. We also need to reconsider how to integrate static property setters to this mechanism. So, basically, this involves
+    large refactoring to renew our JSObject::put and JSObject::getOwnPropertySlot.
+    
+    To work-around for now, we add a new TypeInfo flag, HasPutPropertySecurityCheck . And adding this flag to DOM objects
+    that implements the addition checks. We also add doPutPropertySecurityCheck method hook to perform the check in JSObject.
+    When we found this flag at (1), we perform doPutPropertySecurityCheck to properly perform the checks.
+    
+    Since our JSObject::put code is old and it does not match against the spec now, we should refactor it largely. This is tracked separately in [1].
+    
+    [1]: https://bugs.webkit.org/show_bug.cgi?id=200562
+    
+    * runtime/ClassInfo.h:
+    * runtime/JSCJSValue.cpp:
+    (JSC::JSValue::putToPrimitive):
+    * runtime/JSCell.cpp:
+    (JSC::JSCell::doPutPropertySecurityCheck):
+    * runtime/JSCell.h:
+    * runtime/JSObject.cpp:
+    (JSC::JSObject::putInlineSlow):
+    (JSC::JSObject::getOwnPropertyDescriptor):
+    * runtime/JSObject.h:
+    (JSC::JSObject::doPutPropertySecurityCheck):
+    * runtime/JSTypeInfo.h:
+    (JSC::TypeInfo::hasPutPropertySecurityCheck const):
+    
+    Source/WebCore:
+    
+    Test: http/tests/security/cross-frame-access-object-put-optimization.html
+    
+    * bindings/js/JSDOMWindowCustom.cpp:
+    (WebCore::JSDOMWindow::doPutPropertySecurityCheck):
+    * bindings/js/JSLocationCustom.cpp:
+    (WebCore::JSLocation::doPutPropertySecurityCheck):
+    * bindings/scripts/CodeGeneratorJS.pm:
+    (GenerateHeader):
+    * bindings/scripts/test/JS/JSTestActiveDOMObject.h:
+    
+    LayoutTests:
+    
+    * http/tests/security/cross-frame-access-object-put-optimization-expected.txt: Added.
+    * http/tests/security/cross-frame-access-object-put-optimization.html: Added.
+    * http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html: Added.
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248494 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2019-08-09  Yusuke Suzuki  <ysuzuki@apple.com>
+
+            Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive
+            https://bugs.webkit.org/show_bug.cgi?id=199864
+
+            Reviewed by Saam Barati.
+
+            Our JSObject::put implementation is not correct in term of the spec. Our [[Put]] implementation is something like this.
+
+                JSObject::put(object):
+                    if (can-do-fast-path(object))
+                        return fast-path(object);
+                    // slow-path
+                    do {
+                        object-put-check-and-setter-calls(object); // (1)
+                        object = object->prototype;
+                    } while (is-object(object));
+                    return do-put(object);
+
+            Since JSObject::put is registered in the methodTable, the derived classes can override it. Some of classes are adding
+            extra checks to this put.
+
+                Derived::put(object):
+                    if (do-extra-check(object))
+                        fail
+                    return JSObject::put(object)
+
+            The problem is that Derived::put is only called when the |this| object is the Derived class. When traversing [[Prototype]] in
+            JSObject::put, at (1), we do not perform the extra checks added in Derived::put even if `object` is Derived one. This means that
+            we skip the check.
+
+            Currently, JSObject::put and WebCore checking mechanism are broken. JSObject::put should call getOwnPropertySlot at (1) to
+            perform the additional checks. This behavior is matching against the spec. However, currently, our JSObject::getOwnPropertySlot
+            does not propagate setter information. This is required to cache cacheable [[Put]] at (1) for CustomValue, CustomAccessor, and
+            Accessors. We also need to reconsider how to integrate static property setters to this mechanism. So, basically, this involves
+            large refactoring to renew our JSObject::put and JSObject::getOwnPropertySlot.
+
+            To work-around for now, we add a new TypeInfo flag, HasPutPropertySecurityCheck . And adding this flag to DOM objects
+            that implements the addition checks. We also add doPutPropertySecurityCheck method hook to perform the check in JSObject.
+            When we found this flag at (1), we perform doPutPropertySecurityCheck to properly perform the checks.
+
+            Since our JSObject::put code is old and it does not match against the spec now, we should refactor it largely. This is tracked separately in [1].
+
+            [1]: https://bugs.webkit.org/show_bug.cgi?id=200562
+
+            * runtime/ClassInfo.h:
+            * runtime/JSCJSValue.cpp:
+            (JSC::JSValue::putToPrimitive):
+            * runtime/JSCell.cpp:
+            (JSC::JSCell::doPutPropertySecurityCheck):
+            * runtime/JSCell.h:
+            * runtime/JSObject.cpp:
+            (JSC::JSObject::putInlineSlow):
+            (JSC::JSObject::getOwnPropertyDescriptor):
+            * runtime/JSObject.h:
+            (JSC::JSObject::doPutPropertySecurityCheck):
+            * runtime/JSTypeInfo.h:
+            (JSC::TypeInfo::hasPutPropertySecurityCheck const):
+
+2019-08-12  Alan Coon  <alancoon@apple.com>
+
</ins><span class="cx">         Cherry-pick r248027. rdar://problem/53836556
</span><span class="cx"> 
</span><span class="cx">     [JSC] Emit write barrier after storing instead of before storing
</span></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreruntimeClassInfoh"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/runtime/ClassInfo.h (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/runtime/ClassInfo.h     2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/runtime/ClassInfo.h        2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -79,6 +79,9 @@
</span><span class="cx">     using GetOwnPropertySlotByIndexFunctionPtr = bool (*)(JSObject*, ExecState*, unsigned, PropertySlot&);
</span><span class="cx">     GetOwnPropertySlotByIndexFunctionPtr WTF_METHOD_TABLE_ENTRY(getOwnPropertySlotByIndex);
</span><span class="cx"> 
</span><ins>+    using DoPutPropertySecurityCheckFunctionPtr = void (*)(JSObject*, ExecState*, PropertyName, PutPropertySlot&);
+    DoPutPropertySecurityCheckFunctionPtr METHOD_TABLE_ENTRY(doPutPropertySecurityCheck);
+
</ins><span class="cx">     using ToThisFunctionPtr = JSValue (*)(JSCell*, ExecState*, ECMAMode);
</span><span class="cx">     ToThisFunctionPtr WTF_METHOD_TABLE_ENTRY(toThis);
</span><span class="cx"> 
</span><span class="lines">@@ -167,6 +170,7 @@
</span><span class="cx">         &ClassName::deletePropertyByIndex, \
</span><span class="cx">         &ClassName::getOwnPropertySlot, \
</span><span class="cx">         &ClassName::getOwnPropertySlotByIndex, \
</span><ins>+        &ClassName::doPutPropertySecurityCheck, \
</ins><span class="cx">         &ClassName::toThis, \
</span><span class="cx">         &ClassName::defaultValue, \
</span><span class="cx">         &ClassName::getOwnPropertyNames, \
</span></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreruntimeJSCJSValuecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCJSValue.cpp (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCJSValue.cpp  2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCJSValue.cpp     2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -162,18 +162,27 @@
</span><span class="cx">         return false;
</span><span class="cx">     JSValue prototype;
</span><span class="cx">     if (propertyName != vm.propertyNames->underscoreProto) {
</span><del>-        for (; !obj->structure(vm)->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
</del><ins>+        while (true) {
+            Structure* structure = obj->structure(vm);
+            if (structure->hasReadOnlyOrGetterSetterPropertiesExcludingProto() || structure->typeInfo().hasPutPropertySecurityCheck())
+                break;
</ins><span class="cx">             prototype = obj->getPrototype(vm, exec);
</span><span class="cx">             RETURN_IF_EXCEPTION(scope, false);
</span><span class="cx"> 
</span><span class="cx">             if (prototype.isNull())
</span><span class="cx">                 return typeError(exec, scope, slot.isStrictMode(), ReadonlyPropertyWriteError);
</span><ins>+            obj = asObject(prototype);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (; ; obj = asObject(prototype)) {
</span><ins>+        Structure* structure = obj->structure(vm);
+        if (UNLIKELY(structure->typeInfo().hasPutPropertySecurityCheck())) {
+            obj->methodTable(vm)->doPutPropertySecurityCheck(obj, exec, propertyName, slot);
+            RETURN_IF_EXCEPTION(scope, false);
+        }
</ins><span class="cx">         unsigned attributes;
</span><del>-        PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes);
</del><ins>+        PropertyOffset offset = structure->get(vm, propertyName, attributes);
</ins><span class="cx">         if (offset != invalidOffset) {
</span><span class="cx">             if (attributes & PropertyAttribute::ReadOnly)
</span><span class="cx">                 return typeError(exec, scope, slot.isStrictMode(), ReadonlyPropertyWriteError);
</span></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreruntimeJSCellcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.cpp (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.cpp      2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.cpp 2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -212,6 +212,11 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSCell::doPutPropertySecurityCheck(JSObject*, ExecState*, PropertyName, PutPropertySlot&)
+{
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
</ins><span class="cx"> void JSCell::getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreruntimeJSCellh"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.h (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.h        2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/runtime/JSCell.h   2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -265,6 +265,7 @@
</span><span class="cx">     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
</span><span class="cx">     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
</span><span class="cx">     static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
</span><ins>+    static NO_RETURN_DUE_TO_CRASH void doPutPropertySecurityCheck(JSObject*, ExecState*, PropertyName, PutPropertySlot&);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreruntimeJSObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.cpp (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.cpp    2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.cpp       2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -790,8 +790,13 @@
</span><span class="cx"> 
</span><span class="cx">     JSObject* obj = this;
</span><span class="cx">     for (;;) {
</span><ins>+        Structure* structure = obj->structure(vm);
+        if (UNLIKELY(structure->typeInfo().hasPutPropertySecurityCheck())) {
+            obj->methodTable(vm)->doPutPropertySecurityCheck(obj, exec, propertyName, slot);
+            RETURN_IF_EXCEPTION(scope, false);
+        }
</ins><span class="cx">         unsigned attributes;
</span><del>-        PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes);
</del><ins>+        PropertyOffset offset = structure->get(vm, propertyName, attributes);
</ins><span class="cx">         if (isValidOffset(offset)) {
</span><span class="cx">             if (attributes & PropertyAttribute::ReadOnly) {
</span><span class="cx">                 ASSERT(this->prototypeChainMayInterceptStoreTo(vm, propertyName) || obj == this);
</span><span class="lines">@@ -801,7 +806,7 @@
</span><span class="cx">             JSValue gs = obj->getDirect(offset);
</span><span class="cx">             if (gs.isGetterSetter()) {
</span><span class="cx">                 // We need to make sure that we decide to cache this property before we potentially execute aribitrary JS.
</span><del>-                if (!structure(vm)->isDictionary())
</del><ins>+                if (!this->structure(vm)->isDictionary())
</ins><span class="cx">                     slot.setCacheableSetter(obj, offset);
</span><span class="cx"> 
</span><span class="cx">                 bool result = callSetter(exec, slot.thisValue(), gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode);
</span><span class="lines">@@ -3468,6 +3473,11 @@
</span><span class="cx">     if (!result)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=200560
+    // This breaks the assumption that getOwnPropertySlot should return "own" property.
+    // We should fix DebuggerScope, ProxyObject etc. to remove this.
+    //
</ins><span class="cx">     // DebuggerScope::getOwnPropertySlot() (and possibly others) may return attributes from the prototype chain
</span><span class="cx">     // but getOwnPropertyDescriptor() should only work for 'own' properties so we exit early if we detect that
</span><span class="cx">     // the property is not an own property.
</span></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.h (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.h      2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/runtime/JSObject.h 2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -168,6 +168,7 @@
</span><span class="cx">     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
</span><span class="cx">     JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
</span><span class="cx">     bool getOwnPropertySlotInline(ExecState*, PropertyName, PropertySlot&);
</span><ins>+    static void doPutPropertySecurityCheck(JSObject*, ExecState*, PropertyName, PutPropertySlot&);
</ins><span class="cx"> 
</span><span class="cx">     // The key difference between this and getOwnPropertySlot is that getOwnPropertySlot
</span><span class="cx">     // currently returns incorrect results for the DOM window (with non-own properties)
</span><span class="lines">@@ -1404,6 +1405,10 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE void JSObject::doPutPropertySecurityCheck(JSObject*, ExecState*, PropertyName, PutPropertySlot&)
+{
+}
+
</ins><span class="cx"> // It may seem crazy to inline a function this large but it makes a big difference
</span><span class="cx"> // since this is function very hot in variable lookup
</span><span class="cx"> template<bool checkNullStructure>
</span></span></pre></div>
<a id="branchessafari608branchSourceJavaScriptCoreruntimeJSTypeInfoh"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/JavaScriptCore/runtime/JSTypeInfo.h (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/JavaScriptCore/runtime/JSTypeInfo.h    2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/JavaScriptCore/runtime/JSTypeInfo.h       2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx"> static const unsigned GetOwnPropertySlotIsImpureForPropertyAbsence = 1 << 14;
</span><span class="cx"> static const unsigned InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero = 1 << 15;
</span><span class="cx"> static const unsigned StructureIsImmortal = 1 << 16;
</span><ins>+static const unsigned HasPutPropertySecurityCheck = 1 << 17;
</ins><span class="cx"> 
</span><span class="cx"> class TypeInfo {
</span><span class="cx"> public:
</span><span class="lines">@@ -96,6 +97,7 @@
</span><span class="cx">     bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); }
</span><span class="cx">     bool getOwnPropertySlotIsImpure() const { return isSetOnFlags2(GetOwnPropertySlotIsImpure); }
</span><span class="cx">     bool getOwnPropertySlotIsImpureForPropertyAbsence() const { return isSetOnFlags2(GetOwnPropertySlotIsImpureForPropertyAbsence); }
</span><ins>+    bool hasPutPropertySecurityCheck() const { return isSetOnFlags2(HasPutPropertySecurityCheck); }
</ins><span class="cx">     bool newImpurePropertyFiresWatchpoints() const { return isSetOnFlags2(NewImpurePropertyFiresWatchpoints); }
</span><span class="cx">     bool isImmutablePrototypeExoticObject() const { return isSetOnFlags2(IsImmutablePrototypeExoticObject); }
</span><span class="cx">     bool interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero() const { return isSetOnFlags2(InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero); }
</span></span></pre></div>
<a id="branchessafari608branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/WebCore/ChangeLog (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/WebCore/ChangeLog      2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/WebCore/ChangeLog 2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -1,5 +1,105 @@
</span><span class="cx"> 2019-08-12  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><ins>+        Cherry-pick r248494. rdar://problem/54171876
+
+    Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive
+    https://bugs.webkit.org/show_bug.cgi?id=199864
+    
+    Reviewed by Saam Barati.
+    
+    Source/JavaScriptCore:
+    
+    Our JSObject::put implementation is not correct in term of the spec. Our [[Put]] implementation is something like this.
+    
+        JSObject::put(object):
+            if (can-do-fast-path(object))
+                return fast-path(object);
+            // slow-path
+            do {
+                object-put-check-and-setter-calls(object); // (1)
+                object = object->prototype;
+            } while (is-object(object));
+            return do-put(object);
+    
+    Since JSObject::put is registered in the methodTable, the derived classes can override it. Some of classes are adding
+    extra checks to this put.
+    
+        Derived::put(object):
+            if (do-extra-check(object))
+                fail
+            return JSObject::put(object)
+    
+    The problem is that Derived::put is only called when the |this| object is the Derived class. When traversing [[Prototype]] in
+    JSObject::put, at (1), we do not perform the extra checks added in Derived::put even if `object` is Derived one. This means that
+    we skip the check.
+    
+    Currently, JSObject::put and WebCore checking mechanism are broken. JSObject::put should call getOwnPropertySlot at (1) to
+    perform the additional checks. This behavior is matching against the spec. However, currently, our JSObject::getOwnPropertySlot
+    does not propagate setter information. This is required to cache cacheable [[Put]] at (1) for CustomValue, CustomAccessor, and
+    Accessors. We also need to reconsider how to integrate static property setters to this mechanism. So, basically, this involves
+    large refactoring to renew our JSObject::put and JSObject::getOwnPropertySlot.
+    
+    To work-around for now, we add a new TypeInfo flag, HasPutPropertySecurityCheck . And adding this flag to DOM objects
+    that implements the addition checks. We also add doPutPropertySecurityCheck method hook to perform the check in JSObject.
+    When we found this flag at (1), we perform doPutPropertySecurityCheck to properly perform the checks.
+    
+    Since our JSObject::put code is old and it does not match against the spec now, we should refactor it largely. This is tracked separately in [1].
+    
+    [1]: https://bugs.webkit.org/show_bug.cgi?id=200562
+    
+    * runtime/ClassInfo.h:
+    * runtime/JSCJSValue.cpp:
+    (JSC::JSValue::putToPrimitive):
+    * runtime/JSCell.cpp:
+    (JSC::JSCell::doPutPropertySecurityCheck):
+    * runtime/JSCell.h:
+    * runtime/JSObject.cpp:
+    (JSC::JSObject::putInlineSlow):
+    (JSC::JSObject::getOwnPropertyDescriptor):
+    * runtime/JSObject.h:
+    (JSC::JSObject::doPutPropertySecurityCheck):
+    * runtime/JSTypeInfo.h:
+    (JSC::TypeInfo::hasPutPropertySecurityCheck const):
+    
+    Source/WebCore:
+    
+    Test: http/tests/security/cross-frame-access-object-put-optimization.html
+    
+    * bindings/js/JSDOMWindowCustom.cpp:
+    (WebCore::JSDOMWindow::doPutPropertySecurityCheck):
+    * bindings/js/JSLocationCustom.cpp:
+    (WebCore::JSLocation::doPutPropertySecurityCheck):
+    * bindings/scripts/CodeGeneratorJS.pm:
+    (GenerateHeader):
+    * bindings/scripts/test/JS/JSTestActiveDOMObject.h:
+    
+    LayoutTests:
+    
+    * http/tests/security/cross-frame-access-object-put-optimization-expected.txt: Added.
+    * http/tests/security/cross-frame-access-object-put-optimization.html: Added.
+    * http/tests/security/resources/cross-frame-iframe-for-object-put-optimization-test.html: Added.
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248494 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2019-08-09  Yusuke Suzuki  <ysuzuki@apple.com>
+
+            Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive
+            https://bugs.webkit.org/show_bug.cgi?id=199864
+
+            Reviewed by Saam Barati.
+
+            Test: http/tests/security/cross-frame-access-object-put-optimization.html
+
+            * bindings/js/JSDOMWindowCustom.cpp:
+            (WebCore::JSDOMWindow::doPutPropertySecurityCheck):
+            * bindings/js/JSLocationCustom.cpp:
+            (WebCore::JSLocation::doPutPropertySecurityCheck):
+            * bindings/scripts/CodeGeneratorJS.pm:
+            (GenerateHeader):
+            * bindings/scripts/test/JS/JSTestActiveDOMObject.h:
+
+2019-08-12  Alan Coon  <alancoon@apple.com>
+
</ins><span class="cx">         Cherry-pick r248491. rdar://problem/54130636
</span><span class="cx"> 
</span><span class="cx">     Don't allow cross-origin iframes to autofocus
</span></span></pre></div>
<a id="branchessafari608branchSourceWebCorebindingsjsJSDOMWindowCustomcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp      2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp 2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -264,6 +264,25 @@
</span><span class="cx">     return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSDOMWindow::doPutPropertySecurityCheck(JSObject* cell, ExecState* state, PropertyName propertyName, PutPropertySlot&)
+{
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* thisObject = jsCast<JSDOMWindow*>(cell);
+    if (!thisObject->wrapped().frame())
+        return;
+
+    String errorMessage;
+    if (!BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage)) {
+        // We only allow setting "location" attribute cross-origin.
+        if (propertyName == static_cast<JSVMClientData*>(vm.clientData)->builtinNames().locationPublicName())
+            return;
+        throwSecurityError(*state, scope, errorMessage);
+        return;
+    }
+}
+
</ins><span class="cx"> bool JSDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
</span><span class="cx"> {
</span><span class="cx">     VM& vm = state->vm();
</span></span></pre></div>
<a id="branchessafari608branchSourceWebCorebindingsjsJSLocationCustomcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/WebCore/bindings/js/JSLocationCustom.cpp (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/WebCore/bindings/js/JSLocationCustom.cpp       2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/WebCore/bindings/js/JSLocationCustom.cpp  2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -126,6 +126,23 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSLocation::doPutPropertySecurityCheck(JSObject* object, ExecState* state, PropertyName propertyName, PutPropertySlot&)
+{
+    auto* thisObject = jsCast<JSLocation*>(object);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+
+    VM& vm = state->vm();
+
+    // Always allow assigning to the whole location.
+    // However, alllowing assigning of pieces might inadvertently disclose parts of the original location.
+    // So fall through to the access check for those.
+    if (propertyName == static_cast<JSVMClientData*>(vm.clientData)->builtinNames().hrefPublicName())
+        return;
+
+    // Block access and throw if there is a security error.
+    BindingSecurity::shouldAllowAccessToDOMWindow(state, thisObject->wrapped().window(), ThrowSecurityError);
+}
+
</ins><span class="cx"> bool JSLocation::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& putPropertySlot)
</span><span class="cx"> {
</span><span class="cx">     auto* thisObject = jsCast<JSLocation*>(cell);
</span></span></pre></div>
<a id="branchessafari608branchSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm    2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm       2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -2639,6 +2639,11 @@
</span><span class="cx">         push(@headerContent, "    static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n");
</span><span class="cx">         $structureFlags{"JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero"} = 1;
</span><span class="cx">     }
</span><ins>+
+    if ($interface->extendedAttributes->{CheckSecurity}) {
+        push(@headerContent, "    static void doPutPropertySecurityCheck(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PutPropertySlot&);\n");
+        $structureFlags{"JSC::HasPutPropertySecurityCheck"} = 1;
+    }
</ins><span class="cx">     
</span><span class="cx">     if (InstanceOverridesGetOwnPropertyNames($interface)) {
</span><span class="cx">         push(@headerContent, "    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());\n");
</span></span></pre></div>
<a id="branchessafari608branchSourceWebCorebindingsscriptstestJSJSTestActiveDOMObjecth"></a>
<div class="modfile"><h4>Modified: branches/safari-608-branch/Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.h (248576 => 248577)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-608-branch/Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.h       2019-08-12 23:42:43 UTC (rev 248576)
+++ branches/safari-608-branch/Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.h  2019-08-12 23:42:48 UTC (rev 248577)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx">     static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&);
</span><span class="cx">     static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&);
</span><span class="cx">     static TestActiveDOMObject* toWrapped(JSC::VM&, JSC::JSValue);
</span><ins>+    static void doPutPropertySecurityCheck(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PutPropertySlot&);
</ins><span class="cx">     static void destroy(JSC::JSCell*);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="lines">@@ -51,7 +52,7 @@
</span><span class="cx">     static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
</span><span class="cx">     static void heapSnapshot(JSCell*, JSC::HeapSnapshotBuilder&);
</span><span class="cx"> public:
</span><del>-    static const unsigned StructureFlags = Base::StructureFlags | JSC::HasStaticPropertyTable;
</del><ins>+    static const unsigned StructureFlags = Base::StructureFlags | JSC::HasPutPropertySecurityCheck | JSC::HasStaticPropertyTable;
</ins><span class="cx"> protected:
</span><span class="cx">     JSTestActiveDOMObject(JSC::Structure*, JSDOMGlobalObject&, Ref<TestActiveDOMObject>&&);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>