From 5751c8f721439d6abefdeddbbcb7fbcc4b415334 Mon Sep 17 00:00:00 2001 From: Jeremy Roman Date: Tue, 28 Jan 2020 19:57:55 +0000 Subject: [Backport] CVE-2020-6390 - Out of bounds memory access in streams Manual backport of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/2025573: Move ReadableStream requests onto the stack before iteration. This might be subject to concurrent modification by script. (cherry picked from commit 12310ed05f15fea5fa6824c6a6b5d86f81532e25) Bug: 1045874 Contributed-by: Sergei Glazunov Change-Id: I24263327e67e7799df6de3b7592ac641ddf6cfcf Reviewed-by: Allan Sandfeld Jensen --- .../blink/renderer/core/streams/readable_stream_native.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc index 632ea367d68..240f1003a37 100644 --- a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc +++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc @@ -708,7 +708,9 @@ class ReadableStreamNative::TeeEngine::PullAlgorithm final // b. Perform ! ReadableStreamDefaultControllerClose(branch2. // [[readableStreamController]]). for (int branch = 0; branch < 2; ++branch) { - if (!engine_->canceled_[branch]) { + if (!engine_->canceled_[branch] && + ReadableStreamDefaultController::CanCloseOrEnqueue( ++ engine_->controller_[branch])) { ReadableStreamDefaultController::Close( script_state, engine_->controller_[branch]); } @@ -734,7 +736,9 @@ class ReadableStreamNative::TeeEngine::PullAlgorithm final // ReadableStreamDefaultControllerEnqueue(branch2. // [[readableStreamController]], value2). for (int branch = 0; branch < 2; ++branch) { - if (!engine_->canceled_[branch]) { + if (!engine_->canceled_[branch] && + ReadableStreamDefaultController::CanCloseOrEnqueue( + engine_->controller_[branch])) { ReadableStreamDefaultController::Enqueue(script_state, engine_->controller_[branch], value, exception_state); @@ -1532,7 +1536,9 @@ void ReadableStreamNative::Close(ScriptState* script_state, // 5. If ! IsReadableStreamDefaultReader(reader) is true, // a. Repeat for each readRequest that is an element of reader. // [[readRequests]], - for (StreamPromiseResolver* promise : reader->read_requests_) { + HeapDeque> requests; + requests.Swap(reader->read_requests_); + for (StreamPromiseResolver* promise : requests) { // i. Resolve readRequest.[[promise]] with ! // ReadableStreamCreateReadResult(undefined, true, reader. // [[forAuthorCode]]). @@ -1543,7 +1549,7 @@ void ReadableStreamNative::Close(ScriptState* script_state, } // b. Set reader.[[readRequests]] to an empty List. - reader->read_requests_.clear(); + // This is not required since we've already called Swap(). // 6. Resolve reader.[[closedPromise]] with undefined. reader->closed_promise_->ResolveWithUndefined(script_state); -- cgit v1.2.1