|
@@ -0,0 +1,78 @@
|
|
|
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
+From: Reilly Grant <[email protected]>
|
|
|
+Date: Wed, 22 Jul 2020 04:00:16 +0000
|
|
|
+Subject: usb: Prevent iterator invalidation during Promise resolution
|
|
|
+
|
|
|
+This change swaps sets of ScriptPromiseResolvers into local variables in
|
|
|
+a number of places where it was possible for script to execute during
|
|
|
+the call to Resolve() or Reject() and modify the set being iterated
|
|
|
+over, thus invalidating the iterator.
|
|
|
+
|
|
|
+(cherry picked from commit dbc6c3c3652680e287c60b3c6551622748543439)
|
|
|
+
|
|
|
+Bug: 1106773
|
|
|
+Change-Id: Id4eb0cd444a7dbb5de23038ec80f44fee649cfe4
|
|
|
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2304538
|
|
|
+Auto-Submit: Reilly Grant <[email protected]>
|
|
|
+Commit-Queue: James Hollyer <[email protected]>
|
|
|
+Reviewed-by: James Hollyer <[email protected]>
|
|
|
+Cr-Original-Commit-Position: refs/heads/master@{#790217}
|
|
|
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2310964
|
|
|
+Reviewed-by: Reilly Grant <[email protected]>
|
|
|
+Commit-Queue: Reilly Grant <[email protected]>
|
|
|
+Cr-Commit-Position: refs/branch-heads/4183@{#842}
|
|
|
+Cr-Branched-From: 740e9e8a40505392ba5c8e022a8024b3d018ca65-refs/heads/master@{#782793}
|
|
|
+
|
|
|
+diff --git a/third_party/blink/renderer/modules/webusb/usb.cc b/third_party/blink/renderer/modules/webusb/usb.cc
|
|
|
+index de66613d20851dee9a96a8fdcfaec30da9f05b53..e3dc44eb208946aac4a2f836365127ba88c08edd 100644
|
|
|
+--- a/third_party/blink/renderer/modules/webusb/usb.cc
|
|
|
++++ b/third_party/blink/renderer/modules/webusb/usb.cc
|
|
|
+@@ -254,15 +254,22 @@ void USB::OnDeviceRemoved(UsbDeviceInfoPtr device_info) {
|
|
|
+ void USB::OnServiceConnectionError() {
|
|
|
+ service_.reset();
|
|
|
+ client_receiver_.reset();
|
|
|
+- for (ScriptPromiseResolver* resolver : get_devices_requests_)
|
|
|
++
|
|
|
++ // Move the set to a local variable to prevent script execution in Resolve()
|
|
|
++ // from invalidating the iterator used by the loop.
|
|
|
++ HeapHashSet<Member<ScriptPromiseResolver>> get_devices_requests;
|
|
|
++ get_devices_requests.swap(get_devices_requests_);
|
|
|
++ for (auto& resolver : get_devices_requests)
|
|
|
+ resolver->Resolve(HeapVector<Member<USBDevice>>(0));
|
|
|
+- get_devices_requests_.clear();
|
|
|
+
|
|
|
+- for (ScriptPromiseResolver* resolver : get_permission_requests_) {
|
|
|
++ // Move the set to a local variable to prevent script execution in Reject()
|
|
|
++ // from invalidating the iterator used by the loop.
|
|
|
++ HeapHashSet<Member<ScriptPromiseResolver>> get_permission_requests;
|
|
|
++ get_permission_requests.swap(get_permission_requests_);
|
|
|
++ for (auto& resolver : get_permission_requests) {
|
|
|
+ resolver->Reject(MakeGarbageCollected<DOMException>(
|
|
|
+ DOMExceptionCode::kNotFoundError, kNoDeviceSelected));
|
|
|
+ }
|
|
|
+- get_permission_requests_.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ void USB::AddedEventListener(const AtomicString& event_type,
|
|
|
+diff --git a/third_party/blink/renderer/modules/webusb/usb_device.cc b/third_party/blink/renderer/modules/webusb/usb_device.cc
|
|
|
+index 655212ee5dd6c27498b83b8eb5b9e13a14c38a40..17f52e86a134ceb137923b65d1686ce3cbf3bf85 100644
|
|
|
+--- a/third_party/blink/renderer/modules/webusb/usb_device.cc
|
|
|
++++ b/third_party/blink/renderer/modules/webusb/usb_device.cc
|
|
|
+@@ -1125,11 +1125,15 @@ void USBDevice::AsyncReset(ScriptPromiseResolver* resolver, bool success) {
|
|
|
+ void USBDevice::OnConnectionError() {
|
|
|
+ device_.reset();
|
|
|
+ opened_ = false;
|
|
|
+- for (ScriptPromiseResolver* resolver : device_requests_) {
|
|
|
++
|
|
|
++ // Move the set to a local variable to prevent script execution in Reject()
|
|
|
++ // from invalidating the iterator used by the loop.
|
|
|
++ HeapHashSet<Member<ScriptPromiseResolver>> device_requests;
|
|
|
++ device_requests.swap(device_requests_);
|
|
|
++ for (auto& resolver : device_requests) {
|
|
|
+ resolver->Reject(MakeGarbageCollected<DOMException>(
|
|
|
+ DOMExceptionCode::kNotFoundError, kDeviceDisconnected));
|
|
|
+ }
|
|
|
+- device_requests_.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool USBDevice::MarkRequestComplete(ScriptPromiseResolver* resolver) {
|