From 4dbcfb2630419cef49a1d16c9eb44691f4884351 Mon Sep 17 00:00:00 2001 From: Adam Rice Date: Mon, 31 Aug 2020 05:09:21 +0000 Subject: [PATCH] Transferable Streams: Fix crash on deserialization error The transferable streams implementation would crash when it received a chunk that wasn't deserializable, because it failed to enter a ScriptScope before creating a V8 object. Fix it. Also fix the message on the DOMException that is created when deserialization fails. Add a test for deserialization failure. This is hard to trigger in a cross-browser fashion. In this test, we use a WASM module, which can't be transferred to a different site. BUG=1122725 Change-Id: I6e49c69978388357a3c6006cc02dce8f0a949954 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2379417 Commit-Queue: Adam Rice Reviewed-by: Yutaka Hirano Cr-Commit-Position: refs/heads/master@{#803014} --- .../core/streams/transferable_streams.cc | 17 +++++--- .../transferable/deserialize-error.window.js | 39 +++++++++++++++++++ .../resources/create-wasm-module.js | 11 ++++++ .../resources/deserialize-error-frame.html | 39 +++++++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 third_party/blink/web_tests/external/wpt/streams/transferable/deserialize-error.window.js create mode 100644 third_party/blink/web_tests/external/wpt/streams/transferable/resources/create-wasm-module.js create mode 100644 third_party/blink/web_tests/external/wpt/streams/transferable/resources/deserialize-error-frame.html diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc index 048198648b6f0..d26dca6914eea 100644 --- a/third_party/blink/renderer/core/streams/transferable_streams.cc +++ b/third_party/blink/renderer/core/streams/transferable_streams.cc @@ -11,6 +11,7 @@ #include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/core/v8/v8_post_message_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/events/native_event_listener.h" #include "third_party/blink/renderer/core/events/message_event.h" @@ -260,24 +261,28 @@ class CrossRealmTransformErrorListener final : public NativeEventListener { void Invoke(ExecutionContext*, Event*) override { ScriptState* script_state = target_->GetScriptState(); + // Need to enter a script scope to manipulate JavaScript objects. + ScriptState::Scope scope(script_state); + // Common to // https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformreadable // and // https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformwritable. // 1. Let error be a new "DataCloneError" DOMException. - const auto* error = - DOMException::Create("chunk could not be cloned", "DataCloneError"); - auto* message_port = target_->GetMessagePort(); - v8::Local error_value = ToV8(error, script_state); + v8::Local error = V8ThrowDOMException::CreateOrEmpty( + script_state->GetIsolate(), DOMExceptionCode::kDataCloneError, + "chunk could not be cloned"); // 2. Perform ! CrossRealmTransformSendError(port, error). - CrossRealmTransformSendError(script_state, message_port, error_value); + auto* message_port = target_->GetMessagePort(); + CrossRealmTransformSendError(script_state, message_port, error); // 4. Disentangle port. message_port->close(); - target_->HandleError(error_value); + DVLOG(3) << "ErrorListener saw messageerror"; + target_->HandleError(error); } void Trace(Visitor* visitor) const override { diff --git a/third_party/blink/web_tests/external/wpt/streams/transferable/deserialize-error.window.js b/third_party/blink/web_tests/external/wpt/streams/transferable/deserialize-error.window.js new file mode 100644 index 0000000000000..64cf2bbfb1293 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/transferable/deserialize-error.window.js @@ -0,0 +1,39 @@ +// META: script=/common/get-host-info.sub.js +// META: script=resources/create-wasm-module.js +// META: timeout=long + +const { HTTPS_NOTSAMESITE_ORIGIN } = get_host_info(); +const iframe = document.createElement('iframe'); +iframe.src = `${HTTPS_NOTSAMESITE_ORIGIN}/streams/transferable/resources/deserialize-error-frame.html`; + +window.addEventListener('message', async evt => { + // Tests are serialized to make the results deterministic. + switch (evt.data) { + case 'init done': { + const ws = new WritableStream(); + iframe.contentWindow.postMessage(ws, '*', [ws]); + return; + } + + case 'ws done': { + const module = await createWasmModule(); + const rs = new ReadableStream({ + start(controller) { + controller.enqueue(module); + } + }); + iframe.contentWindow.postMessage(rs, '*', [rs]); + return; + } + + case 'rs done': { + iframe.remove(); + } + } +}); + +// Need to do this after adding the listener to ensure we catch the first +// message. +document.body.appendChild(iframe); + +fetch_tests_from_window(iframe.contentWindow); diff --git a/third_party/blink/web_tests/external/wpt/streams/transferable/resources/create-wasm-module.js b/third_party/blink/web_tests/external/wpt/streams/transferable/resources/create-wasm-module.js new file mode 100644 index 0000000000000..37064af95c55c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/transferable/resources/create-wasm-module.js @@ -0,0 +1,11 @@ +// There aren't many cloneable types that will cause an error on +// deserialization. WASM modules have the property that it's an error to +// deserialize them cross-site, which works for our purposes. +async function createWasmModule() { + // It doesn't matter what the module is, so we use one from another + // test. + const response = + await fetch("/wasm/serialization/module/resources/incrementer.wasm"); + const ab = await response.arrayBuffer(); + return WebAssembly.compile(ab); +} diff --git a/third_party/blink/web_tests/external/wpt/streams/transferable/resources/deserialize-error-frame.html b/third_party/blink/web_tests/external/wpt/streams/transferable/resources/deserialize-error-frame.html new file mode 100644 index 0000000000000..5ec2fcda2cdd8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/transferable/resources/deserialize-error-frame.html @@ -0,0 +1,39 @@ + + + +