Title: [219139] trunk/Source/WebKit2
Revision
219139
Author
aes...@apple.com
Date
2017-07-05 11:08:32 -0700 (Wed, 05 Jul 2017)

Log Message

[iOS] WKActionSheetAssistants can outlive their host views
https://bugs.webkit.org/show_bug.cgi?id=174160
<rdar://problem/20638607>

Reviewed by Tim Horton.

WKActionSheetAssistant keeps a raw pointer to its host UIView, and nothing clears it when
the host view is deallocated. If the assistant outlives the view, we can end up accessing a
pointer to a deallocated UIView and crashing.

I don't know how to reproduce such a crash, but this patch guards against it by doing the
following:

1. Make _view a WeakObjCPtr in WKActionSheetAssistant to ensure it gets set to nil when the
   UIView is deallocated.
2. Call -[WKActionSheetAssistant cleanupSheet] when a WKContentView or WKPDFView is
   deallocated, or when the Web process crashes. This will ensure the action sheet is
   dismissed and prevent the user from tapping on an action that's no longer valid.

* UIProcess/ios/WKActionSheetAssistant.mm:
(-[WKActionSheetAssistant superviewForSheet]):
(-[WKActionSheetAssistant _presentationRectForSheetGivenPoint:inHostView:]):
(-[WKActionSheetAssistant presentationRectForElementUsingClosestIndicatedRect]):
(-[WKActionSheetAssistant presentationRectForIndicatedElement]):
(-[WKActionSheetAssistant _shouldPresentAtTouchLocationForElementRect:]):
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView cleanupInteraction]):
* UIProcess/ios/WKPDFView.mm:
(-[WKPDFView dealloc]):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (219138 => 219139)


--- trunk/Source/WebKit2/ChangeLog	2017-07-05 18:01:45 UTC (rev 219138)
+++ trunk/Source/WebKit2/ChangeLog	2017-07-05 18:08:32 UTC (rev 219139)
@@ -1,3 +1,35 @@
+2017-07-05  Andy Estes  <aes...@apple.com>
+
+        [iOS] WKActionSheetAssistants can outlive their host views
+        https://bugs.webkit.org/show_bug.cgi?id=174160
+        <rdar://problem/20638607>
+
+        Reviewed by Tim Horton.
+
+        WKActionSheetAssistant keeps a raw pointer to its host UIView, and nothing clears it when
+        the host view is deallocated. If the assistant outlives the view, we can end up accessing a
+        pointer to a deallocated UIView and crashing.
+
+        I don't know how to reproduce such a crash, but this patch guards against it by doing the
+        following:
+
+        1. Make _view a WeakObjCPtr in WKActionSheetAssistant to ensure it gets set to nil when the
+           UIView is deallocated.
+        2. Call -[WKActionSheetAssistant cleanupSheet] when a WKContentView or WKPDFView is
+           deallocated, or when the Web process crashes. This will ensure the action sheet is
+           dismissed and prevent the user from tapping on an action that's no longer valid.
+
+        * UIProcess/ios/WKActionSheetAssistant.mm:
+        (-[WKActionSheetAssistant superviewForSheet]):
+        (-[WKActionSheetAssistant _presentationRectForSheetGivenPoint:inHostView:]):
+        (-[WKActionSheetAssistant presentationRectForElementUsingClosestIndicatedRect]):
+        (-[WKActionSheetAssistant presentationRectForIndicatedElement]):
+        (-[WKActionSheetAssistant _shouldPresentAtTouchLocationForElementRect:]):
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView cleanupInteraction]):
+        * UIProcess/ios/WKPDFView.mm:
+        (-[WKPDFView dealloc]):
+
 2017-07-05  Frederic Wang  <fw...@igalia.com>
 
         Move ScrolledContentsLayer property to ScrollingStateScrollingNode

Modified: trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm (219138 => 219139)


--- trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm	2017-07-05 18:01:45 UTC (rev 219138)
+++ trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm	2017-07-05 18:08:32 UTC (rev 219139)
@@ -89,7 +89,7 @@
     RetainPtr<WKActionSheet> _interactionSheet;
     RetainPtr<_WKActivatedElementInfo> _elementInfo;
     std::optional<WebKit::InteractionInformationAtPosition> _positionInformation;
-    UIView *_view;
+    WeakObjCPtr<UIView> _view;
     BOOL _needsLinkIndicator;
     BOOL _isPresentingDDUserInterface;
     BOOL _hasPendingActionSheet;
@@ -130,7 +130,8 @@
 
 - (UIView *)superviewForSheet
 {
-    UIView *view = [_view window];
+    UIView *view = _view.getAutoreleased();
+    UIView *superview = [view window];
 
     // FIXME: WebKit has a delegate to retrieve the superview for the image sheet (superviewForImageSheetForWebView)
     // Do we need it in WK2?
@@ -137,7 +138,7 @@
 
     // Find the top most view with a view controller
     UIViewController *controller = nil;
-    UIView *currentView = _view;
+    UIView *currentView = view;
     while (currentView) {
         UIViewController *aController = [UIViewController viewControllerForView:currentView];
         if (aController)
@@ -146,14 +147,14 @@
         currentView = [currentView superview];
     }
     if (controller)
-        view = controller.view;
+        superview = controller.view;
 
-    return view;
+    return superview;
 }
 
 - (CGRect)_presentationRectForSheetGivenPoint:(CGPoint)point inHostView:(UIView *)hostView
 {
-    CGPoint presentationPoint = [hostView convertPoint:point fromView:_view];
+    CGPoint presentationPoint = [hostView convertPoint:point fromView:_view.getAutoreleased()];
     CGRect presentationRect = CGRectMake(presentationPoint.x, presentationPoint.y, 1.0, 1.0);
 
     return CGRectInset(presentationRect, -22.0, -22.0);
@@ -189,7 +190,7 @@
     for (auto path : WebCore::PathUtilities::pathsWithShrinkWrappedRects(indicatedRects, 0)) {
         auto boundingRect = path.fastBoundingRect();
         if (boundingRect.contains(touchLocation))
-            return CGRectInset([view convertRect:(CGRect)boundingRect fromView:_view], -presentationElementRectPadding, -presentationElementRectPadding);
+            return CGRectInset([view convertRect:(CGRect)boundingRect fromView:_view.getAutoreleased()], -presentationElementRectPadding, -presentationElementRectPadding);
     }
 
     return CGRectZero;
@@ -203,7 +204,7 @@
         return CGRectZero;
 
     auto elementBounds = _positionInformation->bounds;
-    return CGRectInset([view convertRect:elementBounds fromView:_view], -presentationElementRectPadding, -presentationElementRectPadding);
+    return CGRectInset([view convertRect:elementBounds fromView:_view.getAutoreleased()], -presentationElementRectPadding, -presentationElementRectPadding);
 }
 
 - (CGRect)initialPresentationRectInHostViewForSheet
@@ -394,8 +395,9 @@
 
 - (BOOL)_shouldPresentAtTouchLocationForElementRect:(CGRect)elementRect
 {
-    auto apparentElementRect = [_view convertRect:elementRect toView:_view.window];
-    auto windowRect = _view.window.bounds;
+    UIView *view = _view.getAutoreleased();
+    auto apparentElementRect = [view convertRect:elementRect toView:view.window];
+    auto windowRect = view.window.bounds;
     apparentElementRect = CGRectIntersection(apparentElementRect, windowRect);
 
     auto leftInset = CGRectGetMinX(apparentElementRect) - CGRectGetMinX(windowRect);

Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (219138 => 219139)


--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2017-07-05 18:01:45 UTC (rev 219138)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2017-07-05 18:08:32 UTC (rev 219139)
@@ -602,7 +602,10 @@
 {
     _webSelectionAssistant = nil;
     _textSelectionAssistant = nil;
+    
+    [_actionSheetAssistant cleanupSheet];
     _actionSheetAssistant = nil;
+    
     _smartMagnificationController = nil;
     _didAccessoryTabInitiateFocus = NO;
     _isExpectingFastSingleTapCommit = NO;

Modified: trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm (219138 => 219139)


--- trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm	2017-07-05 18:01:45 UTC (rev 219138)
+++ trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm	2017-07-05 18:08:32 UTC (rev 219139)
@@ -142,6 +142,7 @@
     [self _clearPages];
     [_pageNumberIndicator removeFromSuperview];
     dispatch_release(_findQueue);
+    [_actionSheetAssistant cleanupSheet];
     [super dealloc];
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to