<!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>[207754] trunk</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/207754">207754</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-10-24 01:04:20 -0700 (Mon, 24 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>ASSERTION FAILED: canvas()-&gt;securityOrigin()-&gt;toString() == cachedImage.origin()-&gt;toString()
https://bugs.webkit.org/show_bug.cgi?id=163242

Patch by Youenn Fablet &lt;youenn@apple.com&gt; on 2016-10-24
Reviewed by Darin Adler.

Source/WebCore:

Test: http/tests/security/cross-origin-cached-images-canvas.html

We were previously on Origin HTTP header to check whether requests were made from different origins.
This is fine for CORS enabled requests but not for GET no CORS requests since they will not have any Origin header.

Now that CachedResource and CachedResourceRequest own their origin, it is best to use these directly.

* loader/cache/CachedResourceLoader.cpp:
(WebCore::isRequestMatchingResourceOrigin):
(WebCore::CachedResourceLoader::shouldUpdateCachedResourceWithCurrentRequest):

LayoutTests:

* http/tests/security/cross-origin-cached-images-canvas-expected.txt: Added.
* http/tests/security/cross-origin-cached-images-canvas.html: Added.
* http/tests/security/resources/cross-origin-cached-image-canvas-iframe.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedResourceLoadercpp">trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestssecuritycrossorigincachedimagescanvasexpectedtxt">trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestssecuritycrossorigincachedimagescanvashtml">trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas.html</a></li>
<li><a href="#trunkLayoutTestshttptestssecurityresourcescrossorigincachedimagecanvasiframehtml">trunk/LayoutTests/http/tests/security/resources/cross-origin-cached-image-canvas-iframe.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (207753 => 207754)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-24 07:52:09 UTC (rev 207753)
+++ trunk/LayoutTests/ChangeLog        2016-10-24 08:04:20 UTC (rev 207754)
</span><span class="lines">@@ -1,5 +1,16 @@
</span><span class="cx"> 2016-10-24  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        ASSERTION FAILED: canvas()-&gt;securityOrigin()-&gt;toString() == cachedImage.origin()-&gt;toString()
+        https://bugs.webkit.org/show_bug.cgi?id=163242
+
+        Reviewed by Darin Adler.
+
+        * http/tests/security/cross-origin-cached-images-canvas-expected.txt: Added.
+        * http/tests/security/cross-origin-cached-images-canvas.html: Added.
+        * http/tests/security/resources/cross-origin-cached-image-canvas-iframe.html: Added.
+
+2016-10-24  Youenn Fablet  &lt;youenn@apple.com&gt;
+
</ins><span class="cx">         Redirections should be upgraded if CSP policy says so
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163544
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttptestssecuritycrossorigincachedimagescanvasexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas-expected.txt (0 => 207754)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas-expected.txt        2016-10-24 08:04:20 UTC (rev 207754)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+CONSOLE MESSAGE: line 27: Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
+Trying to load and render in canvas sequentially the same image from different origins (no cors mode).
+
+PASS: Successfully retrieved image data.
+PASS: The image is not same-origin with this document.
+  
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestssecuritycrossorigincachedimagescanvashtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas.html (0 => 207754)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/security/cross-origin-cached-images-canvas.html        2016-10-24 08:04:20 UTC (rev 207754)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;Trying to load and render in canvas sequentially the same image from different origins (no cors mode).&lt;/p&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+&lt;div&gt;
+    &lt;iframe id=&quot;iframe1&quot;&gt;&lt;/iframe&gt;
+    &lt;iframe id=&quot;iframe2&quot;&gt;&lt;/iframe&gt;
+&lt;/div&gt;
+&lt;script&gt;
+if (window.testRunner) {
+   testRunner.dumpAsText();
+   testRunner.waitUntilDone();
+}
+
+window.addEventListener(&quot;message&quot;, function(event) {
+    document.getElementById('console').innerHTML += event.data + &quot;&lt;br/&gt;&quot;;
+    loadNextFrame();
+});
+
+var iframeURL8000 = &quot;http://127.0.0.1:8000/security/resources/cross-origin-cached-image-canvas-iframe.html&quot;;
+var iframeURL8080 = &quot;http://127.0.0.1:8080/security/resources/cross-origin-cached-image-canvas-iframe.html&quot;;
+
+var allowAllImage = &quot;http://127.0.0.1:8000/security/resources/abe-allow-star.php?allowCache&quot;;
+
+var counter = 0;
+function loadNextFrame()
+{
+    counter++;
+    if (counter == 1)
+        document.getElementById('iframe1').src = iframeURL8000 + &quot;#&quot; +
+            encodeURIComponent(JSON.stringify({node: &quot;img&quot;, url: allowAllImage, shouldPass:true, id: 1}));
+    else if (counter == 2)
+        document.getElementById('iframe2').src = iframeURL8080 + &quot;#&quot; +
+            encodeURIComponent(JSON.stringify({node: &quot;img&quot;, url: allowAllImage, shouldPass:false, id: 2}));
+    else if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+loadNextFrame();
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestssecurityresourcescrossorigincachedimagecanvasiframehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/security/resources/cross-origin-cached-image-canvas-iframe.html (0 => 207754)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/security/resources/cross-origin-cached-image-canvas-iframe.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/security/resources/cross-origin-cached-image-canvas-iframe.html        2016-10-24 08:04:20 UTC (rev 207754)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;canvas id=&quot;canvas&quot;&gt;
+&lt;img id=&quot;img&quot; onload=&quot;drawInCanvas()&quot;&gt;&lt;/img&gt;
+&lt;script&gt;
+var test = JSON.parse(decodeURIComponent(location.hash.substring(1)));
+
+function logError()
+{
+    parent.postMessage((!test.shouldPass ? &quot;PASS&quot;: &quot;FAIL&quot;) + &quot;: The image is not same-origin with this document.&quot;, &quot;*&quot;);
+}
+
+function logPass()
+{
+    parent.postMessage((test.shouldPass ? &quot;PASS&quot;: &quot;FAIL&quot;) + &quot;: Successfully retrieved image data.&quot;, &quot;*&quot;);
+}
+
+function drawInCanvas()
+{
+    var canvas = document.getElementById('canvas');
+    var ctx = canvas.getContext('2d');
+    ctx.drawImage(document.getElementById('img'), 0, 0);
+
+    // Grab a pixel to verify that the image is same-origin:
+    try {
+        var pixel = ctx.getImageData(0, 0, 1, 1);
+        logPass();
+    } catch (e) {
+        logError();
+    }
+}
+
+var node = document.getElementById(test.node);
+node.src = test.url;
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (207753 => 207754)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-24 07:52:09 UTC (rev 207753)
+++ trunk/Source/WebCore/ChangeLog        2016-10-24 08:04:20 UTC (rev 207754)
</span><span class="lines">@@ -1,5 +1,23 @@
</span><span class="cx"> 2016-10-24  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        ASSERTION FAILED: canvas()-&gt;securityOrigin()-&gt;toString() == cachedImage.origin()-&gt;toString()
+        https://bugs.webkit.org/show_bug.cgi?id=163242
+
+        Reviewed by Darin Adler.
+
+        Test: http/tests/security/cross-origin-cached-images-canvas.html
+
+        We were previously on Origin HTTP header to check whether requests were made from different origins.
+        This is fine for CORS enabled requests but not for GET no CORS requests since they will not have any Origin header.
+
+        Now that CachedResource and CachedResourceRequest own their origin, it is best to use these directly.
+
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::isRequestMatchingResourceOrigin):
+        (WebCore::CachedResourceLoader::shouldUpdateCachedResourceWithCurrentRequest):
+
+2016-10-24  Youenn Fablet  &lt;youenn@apple.com&gt;
+
</ins><span class="cx">         Remove CachedResource::passesSameOriginPolicyCheck
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163593
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedResourceLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (207753 => 207754)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp        2016-10-24 07:52:09 UTC (rev 207753)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp        2016-10-24 08:04:20 UTC (rev 207754)
</span><span class="lines">@@ -550,6 +550,17 @@
</span><span class="cx">     return !newRequest.isNull();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline bool originsMatch(const CachedResourceRequest&amp; request, const CachedResource&amp; resource)
+{
+    if (request.origin() == resource.origin())
+        return true;
+    if (!request.origin() || !resource.origin())
+        return false;
+    // We use string comparison as this is how they are serialized as HTTP Origin header value.
+    // This is in particular useful for unique origins that are serialized as &quot;null&quot;
+    return request.origin()-&gt;toString() == resource.origin()-&gt;toString();
+}
+
</ins><span class="cx"> bool CachedResourceLoader::shouldUpdateCachedResourceWithCurrentRequest(const CachedResource&amp; resource, const CachedResourceRequest&amp; request)
</span><span class="cx"> {
</span><span class="cx">     // WebKit is not supporting CORS for fonts (https://bugs.webkit.org/show_bug.cgi?id=86817), no need to update the resource before reusing it.
</span><span class="lines">@@ -583,7 +594,7 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (resource.options().mode != request.options().mode || request.resourceRequest().httpOrigin() != resource.resourceRequest().httpOrigin())
</del><ins>+    if (resource.options().mode != request.options().mode || !originsMatch(request, resource))
</ins><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="cx">     if (resource.options().redirect != request.options().redirect &amp;&amp; resource.hasRedirections())
</span></span></pre>
</div>
</div>

</body>
</html>