Title: [292293] trunk
Revision
292293
Author
you...@apple.com
Date
2022-04-04 10:07:24 -0700 (Mon, 04 Apr 2022)

Log Message

CORS: Allow particular Range header values without a preflight
https://bugs.webkit.org/show_bug.cgi?id=231174
<rdar://problem/84101544>

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

* web-platform-tests/fetch/range/general.any-expected.txt:
* web-platform-tests/fetch/range/general.any.js:
* web-platform-tests/fetch/range/general.any.worker-expected.txt:
* web-platform-tests/fetch/range/resources/long-wav.py:

Source/WebCore:

Covered by updated tests.

* platform/network/HTTPParsers.cpp:

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (292292 => 292293)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-04-04 16:59:04 UTC (rev 292292)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-04-04 17:07:24 UTC (rev 292293)
@@ -1,3 +1,16 @@
+2022-04-04  Youenn Fablet  <you...@apple.com>
+
+        CORS: Allow particular Range header values without a preflight
+        https://bugs.webkit.org/show_bug.cgi?id=231174
+        <rdar://problem/84101544>
+
+        Reviewed by Alex Christensen.
+
+        * web-platform-tests/fetch/range/general.any-expected.txt:
+        * web-platform-tests/fetch/range/general.any.js:
+        * web-platform-tests/fetch/range/general.any.worker-expected.txt:
+        * web-platform-tests/fetch/range/resources/long-wav.py:
+
 2022-04-02  Patrick Griffis  <pgrif...@igalia.com>
 
         CSP: Improve compatibility of source matching

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any-expected.txt (292292 => 292293)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any-expected.txt	2022-04-04 16:59:04 UTC (rev 292292)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any-expected.txt	2022-04-04 17:07:24 UTC (rev 292293)
@@ -4,4 +4,6 @@
 PASS Range header setting allowed for guard type: request
 PASS Privileged header not allowed for guard type: request-no-cors
 PASS Fetch with range header will be sent with Accept-Encoding: identity
+PASS Cross Origin Fetch with non safe range header
+PASS Cross Origin Fetch with safe range header
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.js (292292 => 292293)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.js	2022-04-04 16:59:04 UTC (rev 292292)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.js	2022-04-04 17:07:24 UTC (rev 292293)
@@ -1,4 +1,5 @@
 // META: global=window,worker
+// META: script=/common/get-host-info.sub.js
 // META: script=/common/utils.js
 
 // Helpers that return headers objects with a particular guard
@@ -89,3 +90,47 @@
     assert_equals(await response.json(), 'identity', `Expect identity accept-encoding if range header is ${JSON.stringify(rangeHeader)}`);
   }
 }, `Fetch with range header will be sent with Accept-Encoding: identity`);
+
+promise_test(async () => {
+  const wavURL = new URL(get_host_info().HTTP_REMOTE_ORIGIN + '/fetch/range/resources/long-wav.py');
+  const stashTakeURL = new URL('resources/stash-take.py', location);
+
+  function changeToken() {
+    const stashToken = token();
+    wavURL.searchParams.set('accept-encoding-key', stashToken);
+    stashTakeURL.searchParams.set('key', stashToken);
+  }
+
+  const rangeHeaders = [
+    'bytes=10-9',
+    'bytes=-0',
+    'bytes=0000000000000000000000000000000000000000000000000000000000011-0000000000000000000000000000000000000000000000000000000000111',
+  ];
+
+  for (const rangeHeader of rangeHeaders) {
+    changeToken();
+    await fetch(wavURL, { headers: { Range : rangeHeader} }).then(() => { throw "loaded with range header " + rangeHeader }, () => { });
+  }
+}, `Cross Origin Fetch with non safe range header`);
+
+promise_test(async () => {
+  const wavURL = new URL(get_host_info().HTTP_REMOTE_ORIGIN + '/fetch/range/resources/long-wav.py');
+  const stashTakeURL = new URL('resources/stash-take.py', location);
+
+  function changeToken() {
+    const stashToken = token();
+    wavURL.searchParams.set('accept-encoding-key', stashToken);
+    stashTakeURL.searchParams.set('key', stashToken);
+  }
+
+  const rangeHeaders = [
+    'bytes=0-10',
+    'bytes=0-',
+    'bytes=00000000000000000000000000000000000000000000000000000000011-00000000000000000000000000000000000000000000000000000000000111',
+  ];
+
+  for (const rangeHeader of rangeHeaders) {
+    changeToken();
+    await fetch(wavURL, { headers: { Range: rangeHeader } }).then(() => { }, () => { throw "failed load with range header " + rangeHeader });
+  }
+}, `Cross Origin Fetch with safe range header`);

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker-expected.txt (292292 => 292293)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker-expected.txt	2022-04-04 16:59:04 UTC (rev 292292)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker-expected.txt	2022-04-04 17:07:24 UTC (rev 292293)
@@ -4,4 +4,6 @@
 PASS Range header setting allowed for guard type: request
 PASS Privileged header not allowed for guard type: request-no-cors
 PASS Fetch with range header will be sent with Accept-Encoding: identity
+PASS Cross Origin Fetch with non safe range header
+PASS Cross Origin Fetch with safe range header
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/long-wav.py (292292 => 292293)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/long-wav.py	2022-04-04 16:59:04 UTC (rev 292292)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/long-wav.py	2022-04-04 17:07:24 UTC (rev 292293)
@@ -46,9 +46,15 @@
 
 
 def main(request, response):
+    if request.method == u"OPTIONS":
+        response.status = (404, b"Not Found")
+        response.headers.set(b"Content-Type", b"text/plain")
+        return b"Preflight not accepted"
+
     response.headers.set(b"Content-Type", b"audio/wav")
     response.headers.set(b"Accept-Ranges", b"bytes")
     response.headers.set(b"Cache-Control", b"no-cache")
+    response.headers.set(b"Access-Control-Allow-Origin", request.headers.get(b'Origin', b''))
 
     range_header = request.headers.get(b'Range', b'')
     range_header_match = range_header and re.search(r'^bytes=(\d*)-(\d*)$', isomorphic_decode(range_header))

Modified: trunk/Source/WebCore/ChangeLog (292292 => 292293)


--- trunk/Source/WebCore/ChangeLog	2022-04-04 16:59:04 UTC (rev 292292)
+++ trunk/Source/WebCore/ChangeLog	2022-04-04 17:07:24 UTC (rev 292293)
@@ -1,3 +1,15 @@
+2022-04-04  Youenn Fablet  <you...@apple.com>
+
+        CORS: Allow particular Range header values without a preflight
+        https://bugs.webkit.org/show_bug.cgi?id=231174
+        <rdar://problem/84101544>
+
+        Reviewed by Alex Christensen.
+
+        Covered by updated tests.
+
+        * platform/network/HTTPParsers.cpp:
+
 2022-04-04  Jer Noble  <jer.no...@apple.com>
 
         [Perf] HTMLVideoElement is performing synchronous paints; causing main thread hangs

Modified: trunk/Source/WebCore/platform/network/HTTPParsers.cpp (292292 => 292293)


--- trunk/Source/WebCore/platform/network/HTTPParsers.cpp	2022-04-04 16:59:04 UTC (rev 292292)
+++ trunk/Source/WebCore/platform/network/HTTPParsers.cpp	2022-04-04 17:07:24 UTC (rev 292293)
@@ -36,6 +36,7 @@
 #include "HTTPHeaderField.h"
 #include "HTTPHeaderNames.h"
 #include "ParsedContentType.h"
+#include <wtf/CheckedArithmetic.h>
 #include <wtf/DateMath.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/StringBuilder.h>
@@ -168,6 +169,7 @@
 }
 
 // See RFC 7231, Section 5.3.5 and 3.1.3.2.
+// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
 bool isValidLanguageHeaderValue(const String& value)
 {
     for (unsigned i = 0; i < value.length(); ++i) {
@@ -176,11 +178,6 @@
             continue;
         return false;
     }
-    
-    // FIXME: Validate further by splitting into language tags and optional quality
-    // values (q=) and then check each language tag.
-    // Language tags https://tools.ietf.org/html/rfc7231#section-3.1.3.1
-    // Language tag syntax https://tools.ietf.org/html/bcp47#section-2.1
     return true;
 }
 
@@ -954,9 +951,47 @@
     return accessControlExposeHeaderSet.contains(name);
 }
 
+static bool isSimpleRangeHeaderValue(const String& value)
+{
+    if (!value.startsWith("bytes="_s))
+        return false;
+
+    unsigned start = 0;
+    unsigned end = 0;
+    bool hasHyphen = false;
+
+    for (size_t cptr = 6; cptr < value.length(); ++cptr) {
+        auto character = value[cptr];
+        if (character >= '0' && character <= '9') {
+            if (productOverflows<unsigned>(hasHyphen ? end : start, 10))
+                return false;
+            auto newDecimal = (hasHyphen ? end : start) * 10;
+            auto sum = Checked<unsigned, RecordOverflow>(newDecimal) + Checked<unsigned, RecordOverflow>(character - '0');
+            if (sum.hasOverflowed())
+                return false;
+
+            if (hasHyphen)
+                end = sum.value();
+            else
+                start = sum.value();
+            continue;
+        }
+        if (character == '-' && !hasHyphen) {
+            hasHyphen = true;
+            continue;
+        }
+        return false;
+    }
+
+    return hasHyphen && (!end || start < end);
+}
+
 // Implements https://fetch.spec.whatwg.org/#cors-safelisted-request-header
 bool isCrossOriginSafeRequestHeader(HTTPHeaderName name, const String& value)
 {
+    if (value.length() > 128)
+        return false;
+
     switch (name) {
     case HTTPHeaderName::Accept:
         if (!isValidAcceptHeaderValue(value))
@@ -979,11 +1014,15 @@
             return false;
         break;
     }
+    case HTTPHeaderName::Range:
+        if (!isSimpleRangeHeaderValue(value))
+            return false;
+        break;
     default:
         // FIXME: Should we also make safe other headers (DPR, Downlink, Save-Data...)? That would require validating their values.
         return false;
     }
-    return value.length() <= 128;
+    return true;
 }
 
 // Implements <https://fetch.spec.whatwg.org/#concept-method-normalize>.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to