Title: [234599] trunk/Tools
Revision
234599
Author
wenson_hs...@apple.com
Date
2018-08-06 06:59:04 -0700 (Mon, 06 Aug 2018)

Log Message

[iOS] Layout tests that send HID events cause WebKitTestRunner to crash on recent SDKs
https://bugs.webkit.org/show_bug.cgi?id=188334
<rdar://problem/40630074>

Reviewed by Tim Horton.

To mark the end of previously dispatched IOHID events, HIDEventGenerator currently sends a vendor-defined event
and stores the completion callback ID for the previously dispatched events as vendor-defined data. When this
vendor-defined marker event is handled by the application, we then read the callback ID back from the event, map
it to a completion block, and invoke the completion block to signal that the previous HID event has been
processed.

This callback ID is an unsigned, so we tell IOKit that we need `sizeof(unsigned)` (4 bytes) to store it. On
shipping software, IOKit clamps this to a minimum of 8 bytes, i.e. `sizeof(CFIndex)`. When we later call
IOHIDEventGetIntegerValue to read the value of our vendor-defined data as a CFIndex, we get our expected
callback ID because the buffer was clamped to 8 bytes.

However, on recent iOS SDKs that contain the fix for <rdar://problem/20082284>, IOKit no longer clamps the size
of the vendor-defined data buffer to 8 bytes. This means that when we try to use IOHIDEventGetIntegerValue to
read our callback ID back, we end up getting a CFIndex where the lower 4 bytes are the callback ID we wrote, and
the upper 4 bytes are garbage. In the case where any of these upper 4 bytes are non-zero, we fail to map the
callback ID to a completion handler, and so we never finish dispatching the HID event, causing an exception to
be thrown.

To fix this, we adjust callback ID to be a CFIndex, which matches IOHIDEventGetIntegerValue's return type.

* WebKitTestRunner/ios/HIDEventGenerator.mm:
(+[HIDEventGenerator nextEventCallbackID]):
(-[HIDEventGenerator _sendMarkerHIDEventWithCompletionBlock:]):

Also refactor a bit of `-_sendMarkerHIDEventWithCompletionBlock:` by using auto and move semantics.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (234598 => 234599)


--- trunk/Tools/ChangeLog	2018-08-06 12:59:41 UTC (rev 234598)
+++ trunk/Tools/ChangeLog	2018-08-06 13:59:04 UTC (rev 234599)
@@ -1,3 +1,37 @@
+2018-08-06  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Layout tests that send HID events cause WebKitTestRunner to crash on recent SDKs
+        https://bugs.webkit.org/show_bug.cgi?id=188334
+        <rdar://problem/40630074>
+
+        Reviewed by Tim Horton.
+
+        To mark the end of previously dispatched IOHID events, HIDEventGenerator currently sends a vendor-defined event
+        and stores the completion callback ID for the previously dispatched events as vendor-defined data. When this
+        vendor-defined marker event is handled by the application, we then read the callback ID back from the event, map
+        it to a completion block, and invoke the completion block to signal that the previous HID event has been
+        processed.
+
+        This callback ID is an unsigned, so we tell IOKit that we need `sizeof(unsigned)` (4 bytes) to store it. On
+        shipping software, IOKit clamps this to a minimum of 8 bytes, i.e. `sizeof(CFIndex)`. When we later call
+        IOHIDEventGetIntegerValue to read the value of our vendor-defined data as a CFIndex, we get our expected
+        callback ID because the buffer was clamped to 8 bytes.
+
+        However, on recent iOS SDKs that contain the fix for <rdar://problem/20082284>, IOKit no longer clamps the size
+        of the vendor-defined data buffer to 8 bytes. This means that when we try to use IOHIDEventGetIntegerValue to
+        read our callback ID back, we end up getting a CFIndex where the lower 4 bytes are the callback ID we wrote, and
+        the upper 4 bytes are garbage. In the case where any of these upper 4 bytes are non-zero, we fail to map the
+        callback ID to a completion handler, and so we never finish dispatching the HID event, causing an exception to
+        be thrown.
+
+        To fix this, we adjust callback ID to be a CFIndex, which matches IOHIDEventGetIntegerValue's return type.
+
+        * WebKitTestRunner/ios/HIDEventGenerator.mm:
+        (+[HIDEventGenerator nextEventCallbackID]):
+        (-[HIDEventGenerator _sendMarkerHIDEventWithCompletionBlock:]):
+
+        Also refactor a bit of `-_sendMarkerHIDEventWithCompletionBlock:` by using auto and move semantics.
+
 2018-08-03  Ben Richards  <benton_richa...@apple.com>
 
         We should cache the compiled sandbox profile in a data vault

Modified: trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm (234598 => 234599)


--- trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm	2018-08-06 12:59:41 UTC (rev 234598)
+++ trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm	2018-08-06 13:59:04 UTC (rev 234599)
@@ -171,9 +171,9 @@
     return eventGenerator;
 }
 
-+ (unsigned)nextEventCallbackID
++ (CFIndex)nextEventCallbackID
 {
-    static unsigned callbackID = 0;
+    static CFIndex callbackID = 0;
     return ++callbackID;
 }
 
@@ -479,24 +479,21 @@
 
 - (BOOL)_sendMarkerHIDEventWithCompletionBlock:(void (^)(void))completionBlock
 {
-    unsigned callbackID = [HIDEventGenerator nextEventCallbackID];
-    void (^completionBlockCopy)() = Block_copy(completionBlock);
-    [_eventCallbacks setObject:completionBlockCopy forKey:@(callbackID)];
+    auto callbackID = [HIDEventGenerator nextEventCallbackID];
+    [_eventCallbacks setObject:Block_copy(completionBlock) forKey:@(callbackID)];
 
-    uint64_t machTime = mach_absolute_time();
-    RetainPtr<IOHIDEventRef> markerEvent = adoptCF(IOHIDEventCreateVendorDefinedEvent(kCFAllocatorDefault,
-        machTime,
+    auto markerEvent = adoptCF(IOHIDEventCreateVendorDefinedEvent(kCFAllocatorDefault,
+        mach_absolute_time(),
         kHIDPage_VendorDefinedStart + 100,
         0,
         1,
         (uint8_t*)&callbackID,
-        sizeof(unsigned),
+        sizeof(CFIndex),
         kIOHIDEventOptionNone));
     
     if (markerEvent) {
-        markerEvent.get();
-        dispatch_async(dispatch_get_main_queue(), ^{
-            uint32_t contextID = [UIApplication sharedApplication].keyWindow._contextId;
+        dispatch_async(dispatch_get_main_queue(), [markerEvent = WTFMove(markerEvent)] {
+            auto contextID = [UIApplication sharedApplication].keyWindow._contextId;
             ASSERT(contextID);
             BKSHIDEventSetDigitizerInfo(markerEvent.get(), contextID, false, false, NULL, 0, 0);
             [[UIApplication sharedApplication] _enqueueHIDEvent:markerEvent.get()];
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to