Commit dbc6c3c3 authored by Reilly Grant's avatar Reilly Grant Committed by Commit Bot

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.

Bug: 1106773
Change-Id: Id4eb0cd444a7dbb5de23038ec80f44fee649cfe4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2304538
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Commit-Queue: James Hollyer <jameshollyer@chromium.org>
Reviewed-by: default avatarJames Hollyer <jameshollyer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790217}
parent 76087000
......@@ -249,15 +249,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,
......
......@@ -1132,11 +1132,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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment