Title: [282365] trunk
Revision
282365
Author
cdu...@apple.com
Date
2021-09-13 15:06:45 -0700 (Mon, 13 Sep 2021)

Log Message

Crash under WebPage::runJavaScript()
https://bugs.webkit.org/show_bug.cgi?id=230223
<rdar://80172436>

Reviewed by Brady Eidson.

Source/WebKit:

The resolveFunction() was capturing `frame = makeRef(frame)` and then calling `frame->coreFrame()->script()`.
This would lead to a null dereference crash in the case where the core frame gets destroyed before the JS
promise gets resolved. Protecting the WebFrame does not keep the core Frame alive as WebFrame::m_coreFrame
is merely a WeakPtr. To address the issue, the lambda now also protects the core frame and uses it to get
the script controller.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::runJavaScript):

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm:
(-[AsyncJSUIDelegate initWithAlertHandler:]):
(-[AsyncJSUIDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (282364 => 282365)


--- trunk/Source/WebKit/ChangeLog	2021-09-13 22:01:40 UTC (rev 282364)
+++ trunk/Source/WebKit/ChangeLog	2021-09-13 22:06:45 UTC (rev 282365)
@@ -1,3 +1,20 @@
+2021-09-13  Chris Dumez  <cdu...@apple.com>
+
+        Crash under WebPage::runJavaScript()
+        https://bugs.webkit.org/show_bug.cgi?id=230223
+        <rdar://80172436>
+
+        Reviewed by Brady Eidson.
+
+        The resolveFunction() was capturing `frame = makeRef(frame)` and then calling `frame->coreFrame()->script()`.
+        This would lead to a null dereference crash in the case where the core frame gets destroyed before the JS
+        promise gets resolved. Protecting the WebFrame does not keep the core Frame alive as WebFrame::m_coreFrame
+        is merely a WeakPtr. To address the issue, the lambda now also protects the core frame and uses it to get
+        the script controller.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::runJavaScript):
+
 2021-09-13  Per Arne Vollan  <pvol...@apple.com>
 
         Send preference updates to the GPU process

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (282364 => 282365)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-09-13 22:01:40 UTC (rev 282364)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-09-13 22:06:45 UTC (rev 282365)
@@ -3722,11 +3722,11 @@
     }
 #endif
 
-    auto resolveFunction = [world = makeRef(*world), frame = makeRef(*frame), completionHandler = WTFMove(completionHandler)] (ValueOrException result) mutable {
+    auto resolveFunction = [world = makeRef(*world), frame = Ref { *frame }, coreFrame = Ref { *frame->coreFrame() }, completionHandler = WTFMove(completionHandler)] (ValueOrException result) mutable {
         RefPtr<SerializedScriptValue> serializedResultValue;
         if (result) {
             serializedResultValue = SerializedScriptValue::create(frame->jsContextForWorld(world.ptr()),
-                toRef(frame->coreFrame()->script().globalObject(world->coreWorld()), result.value()), nullptr);
+                toRef(coreFrame->script().globalObject(world->coreWorld()), result.value()), nullptr);
         }
 
         IPC::DataReference dataReference;

Modified: trunk/Tools/ChangeLog (282364 => 282365)


--- trunk/Tools/ChangeLog	2021-09-13 22:01:40 UTC (rev 282364)
+++ trunk/Tools/ChangeLog	2021-09-13 22:06:45 UTC (rev 282365)
@@ -1,3 +1,18 @@
+2021-09-13  Chris Dumez  <cdu...@apple.com>
+
+        Crash under WebPage::runJavaScript()
+        https://bugs.webkit.org/show_bug.cgi?id=230223
+        <rdar://80172436>
+
+        Reviewed by Brady Eidson.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm:
+        (-[AsyncJSUIDelegate initWithAlertHandler:]):
+        (-[AsyncJSUIDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
+        (TestWebKitAPI::TEST):
+
 2021-09-13  Tyler Wilcock  <tyle...@apple.com>
 
         AX: Make PDFs loaded via <embed> accessible

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm (282364 => 282365)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm	2021-09-13 22:01:40 UTC (rev 282364)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm	2021-09-13 22:06:45 UTC (rev 282365)
@@ -27,8 +27,10 @@
 
 #import "PlatformUtilities.h"
 #import "Test.h"
+#import "TestUIDelegate.h"
 #import "TestWKWebView.h"
 #import <WebKit/WKContentWorld.h>
+#import <WebKit/WKFrameInfo.h>
 #import <WebKit/WKProcessPoolPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 
@@ -280,5 +282,43 @@
     TestWebKitAPI::Util::run(&done);
 }
 
+TEST(AsyncFunction, PromiseDetachedFrame)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+    auto uiDelegate = adoptNS([[TestUIDelegate alloc] init]);
+    [webView setUIDelegate:uiDelegate.get()];
+
+    __block RetainPtr<WKFrameInfo> subframe;
+    __block bool doneGettingSubframe = false;
+    uiDelegate.get().runJavaScriptAlertPanelWithMessage = ^(WKWebView *, NSString *, WKFrameInfo * frame, void (^completionHandler)(void)) {
+        subframe = frame;
+        doneGettingSubframe = true;
+        completionHandler();
+    };
+
+    [webView synchronouslyLoadHTMLString:@"<iframe src=''></iframe>"];
+
+    TestWebKitAPI::Util::run(&doneGettingSubframe);
+
+    ASSERT_TRUE(!!subframe);
+    EXPECT_FALSE([subframe isMainFrame]);
+
+    auto pid = [webView _webProcessIdentifier];
+    EXPECT_NE(pid, 0);
+
+    NSString *functionBody = @"return new Promise(function(resolve, reject) { setTimeout(function(){ top.setTimeout(function() { resolve(42); }, 100); top.document.querySelector('iframe').remove(); }, 0); })";
+
+    bool done = false;
+    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:subframe.get() inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
+        EXPECT_NULL(error);
+        EXPECT_TRUE([result isKindOfClass:[NSNumber class]]);
+        EXPECT_TRUE([result isEqualToNumber:@42]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    EXPECT_EQ([webView _webProcessIdentifier], pid);
 }
 
+}
+
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to