⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 268904 in webkit


Ignore:
Timestamp:
Oct 22, 2020, 9:25:13 PM (6 years ago)
Author:
commit-queue@webkit.org
Message:

Null check platformStrategies when making blob read stream for an NSURLRequest
https://bugs.webkit.org/show_bug.cgi?id=218112
<rdar://problem/70507102>

Patch by Alex Christensen <achristensen@webkit.org> on 2020-10-22
Reviewed by Wenson Hsieh.

Source/WebCore:

r266187 made it possible to create a DataTransfer without a user event, which allows you to make a FileList,
which allows you to submit a multipart form without a user event that calls decidePolicyForNavigationAction
with a request that has a form data body that would make a blob upload stream. This causes us to use
platformStrategies in the UI process, which dereferences null. Since the blob only really exists in the network
process, just return a nil HTTPBody in such an exotic case instead of crashing.

Covered by an API test that would hit this crash. Web platform tests were insufficient because WebKitTestRunner does not
access WKNavigationAction.request, but Safari does.

  • platform/PlatformStrategies.cpp:

(WebCore::hasPlatformStrategies):

  • platform/PlatformStrategies.h:
  • platform/network/FormData.cpp:

(WebCore::FormData::containsBlobElement const):
(WebCore::FormData::resolveBlobReferences):

  • platform/network/FormData.h:
  • platform/network/cf/FormDataStreamCFNet.cpp:

(WebCore::createHTTPBodyCFReadStream):

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/NavigationAction.mm:

(TEST):

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r268902 r268904  
     12020-10-22  Alex Christensen  <achristensen@webkit.org>
     2
     3        Null check platformStrategies when making blob read stream for an NSURLRequest
     4        https://bugs.webkit.org/show_bug.cgi?id=218112
     5        <rdar://problem/70507102>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        r266187 made it possible to create a DataTransfer without a user event, which allows you to make a FileList,
     10        which allows you to submit a multipart form without a user event that calls decidePolicyForNavigationAction
     11        with a request that has a form data body that would make a blob upload stream.  This causes us to use
     12        platformStrategies in the UI process, which dereferences null.  Since the blob only really exists in the network
     13        process, just return a nil HTTPBody in such an exotic case instead of crashing.
     14
     15        Covered by an API test that would hit this crash.  Web platform tests were insufficient because WebKitTestRunner does not
     16        access WKNavigationAction.request, but Safari does.
     17
     18        * platform/PlatformStrategies.cpp:
     19        (WebCore::hasPlatformStrategies):
     20        * platform/PlatformStrategies.h:
     21        * platform/network/FormData.cpp:
     22        (WebCore::FormData::containsBlobElement const):
     23        (WebCore::FormData::resolveBlobReferences):
     24        * platform/network/FormData.h:
     25        * platform/network/cf/FormDataStreamCFNet.cpp:
     26        (WebCore::createHTTPBodyCFReadStream):
     27
    1282020-10-22  Simon Fraser  <simon.fraser@apple.com>
    229
  • trunk/Source/WebCore/platform/PlatformStrategies.cpp

    r196174 r268904  
    3131static PlatformStrategies* s_platformStrategies;
    3232
     33bool hasPlatformStrategies()
     34{
     35    return !!s_platformStrategies;
     36}
     37
    3338PlatformStrategies* platformStrategies()
    3439{
  • trunk/Source/WebCore/platform/PlatformStrategies.h

    r257551 r268904  
    8282};
    8383
     84bool hasPlatformStrategies();
    8485WEBCORE_EXPORT PlatformStrategies* platformStrategies();
    8586WEBCORE_EXPORT void setPlatformStrategies(PlatformStrategies*);
  • trunk/Source/WebCore/platform/network/FormData.cpp

    r266330 r268904  
    317317}
    318318
     319bool FormData::containsBlobElement() const
     320{
     321    for (auto& element : m_elements) {
     322        if (WTF::holds_alternative<FormDataElement::EncodedBlobData>(element.data))
     323            return true;
     324    }
     325    return false;
     326}
     327
    319328Ref<FormData> FormData::resolveBlobReferences(BlobRegistryImpl* blobRegistryImpl)
    320329{
    321330    // First check if any blobs needs to be resolved, or we can take the fast path.
    322     bool hasBlob = false;
    323     for (auto& element : m_elements) {
    324         if (WTF::holds_alternative<FormDataElement::EncodedBlobData>(element.data)) {
    325             hasBlob = true;
    326             break;
    327         }
    328     }
    329 
    330     if (!hasBlob)
     331    if (!containsBlobElement())
    331332        return *this;
    332333
  • trunk/Source/WebCore/platform/network/FormData.h

    r266087 r268904  
    222222    // If the FormData has no blob references to resolve, this is returned.
    223223    WEBCORE_EXPORT Ref<FormData> resolveBlobReferences(BlobRegistryImpl* = nullptr);
     224    bool containsBlobElement() const;
    224225
    225226    WEBCORE_EXPORT FormDataForUpload prepareForUpload();
  • trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp

    r254089 r268904  
    3232#include "BlobRegistryImpl.h"
    3333#include "FormData.h"
     34#include "PlatformStrategies.h"
    3435#include <sys/stat.h>
    3536#include <sys/types.h>
     
    371372RetainPtr<CFReadStreamRef> createHTTPBodyCFReadStream(FormData& formData)
    372373{
     374    if (!hasPlatformStrategies() && formData.containsBlobElement())
     375        return nullptr;
     376
    373377    auto resolvedFormData = formData.resolveBlobReferences();
    374378    auto dataForUpload = resolvedFormData->prepareForUpload();
  • trunk/Tools/ChangeLog

    r268896 r268904  
     12020-10-22  Alex Christensen  <achristensen@webkit.org>
     2
     3        Null check platformStrategies when making blob read stream for an NSURLRequest
     4        https://bugs.webkit.org/show_bug.cgi?id=218112
     5        <rdar://problem/70507102>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        * TestWebKitAPI/Tests/WebKitCocoa/NavigationAction.mm:
     10        (TEST):
     11
    1122020-10-22  Jonathan Bedard  <jbedard@apple.com>
    213
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NavigationAction.mm

    r260366 r268904  
    2626#import "config.h"
    2727
     28#import "HTTPServer.h"
    2829#import "PlatformUtilities.h"
    2930#import "Test.h"
     31#import "TestNavigationDelegate.h"
    3032#import "TestWKWebView.h"
    3133#import <WebKit/WKNavigationActionPrivate.h>
     
    176178    EXPECT_FALSE(navigationDelegate.get().navigationAction._shouldPerformDownload);
    177179}
     180
     181TEST(WKNavigationAction, BlobRequestBody)
     182{
     183    NSString *html = @""
     184        "<script>"
     185            "function bodyLoaded() {"
     186                "const form = Object.assign(document.createElement('form'), {"
     187                    "action: '/formAction', method: 'POST', enctype: 'multipart/form-data',"
     188                "});"
     189                "document.body.append(form);"
     190                "const fileInput = Object.assign(document.createElement('input'), {"
     191                    "type: 'file', name: 'file',"
     192                "});"
     193                "form.append(fileInput);"
     194                "const dataTransfer = new DataTransfer;"
     195                "dataTransfer.items.add(new File(['a'], 'filename'));"
     196                "fileInput.files = dataTransfer.files;"
     197                "form.submit();"
     198            "}"
     199        "</script>"
     200        "<body onload='bodyLoaded()'>";
     201    auto delegate = [[TestNavigationDelegate new] autorelease];
     202    auto webView = [[WKWebView new] autorelease];
     203    webView.navigationDelegate = delegate;
     204    __block bool done = false;
     205    delegate.decidePolicyForNavigationAction = ^(WKNavigationAction *action, void (^completionHandler)(WKNavigationActionPolicy)) {
     206        EXPECT_NULL(action.request.HTTPBody);
     207        if ([action.request.URL.absoluteString isEqualToString:@"about:blank"])
     208            completionHandler(WKNavigationActionPolicyAllow);
     209        else {
     210            EXPECT_WK_STREQ(action.request.URL.absoluteString, "/formAction");
     211            completionHandler(WKNavigationActionPolicyCancel);
     212            done = true;
     213        }
     214    };
     215    [webView loadHTMLString:html baseURL:nil];
     216    TestWebKitAPI::Util::run(&done);
     217}
Note: See TracChangeset for help on using the changeset viewer.