ports/www/qt5-webengine/files/patch-security-rollup
Jason E. Hale 94ccf453a2 www/qt5-webengine: Address security vulnerabilities
Patched with security patches up to Chromium version: 121.0.6167.160

While here, remove unneed extra-patch. All supported versions of FreeBSD
have mempcpy(3).

MFH:		2024Q1
Security:	bbcb1584-c068-11ee-bdd6-4ccc6adda413,
		dc9e5237-c197-11ee-86bb-a8a1599412c6,
		19047673-c680-11ee-86bb-a8a1599412c6
2024-02-10 15:15:08 -05:00

2509 lines
117 KiB
Text
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Add security patches to this file.
Addresses the following security issues:
- CVE-2023-6347
- CVE-2023-6510
- Security bug 1488199
- CVE-2023-6345
- CVE-2023-6702
- Security bug 1505632
- CVE-2024-0222
- CVE-2024-0333
- CVE-2024-0518
- CVE-2024-0519
- Security bug 1506535
- CVE-2023-7024
- CVE-2024-0224
- Security bug 1511689
- CVE-2024-0807
- CVE-2024-0808
- Security bug 1519980
- CVE-2024-1077
- CVE-2024-1060
- CVE-2024-1283
From 8ca846140881c9480b18bc9645b38fb9ea565ea3 Mon Sep 17 00:00:00 2001
From: Ken Rockot <rockot@google.com>
Date: Thu, 16 Nov 2023 23:23:22 +0000
Subject: [PATCH] [Backport] CVE-2023-6347: Use after free in Mojo
Cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5038080:
Reland: Fix IPC Channel pipe teardown
This is a reland with the new test temporarily disabled on Android
until it can run without disrupting other tests.
(cherry picked from commit cd4c1f165c16c6d8161b5372ef7f61c715e01a42)
Fixed: 1494461
Change-Id: If1d83c2dce62020f78dd50abc460973759002a1a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5015115
Commit-Queue: Ken Rockot <rockot@google.com>
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1221953}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5038080
Auto-Submit: Ken Rockot <rockot@google.com>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/branch-heads/6045@{#1383}
Cr-Branched-From: 905e8bdd32d891451d94d1ec71682e989da2b0a1-refs/heads/main@{#1204232}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/522256
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
chromium/ipc/ipc_mojo_bootstrap.cc | 43 ++++++++++++++++++++++--------
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/chromium/ipc/ipc_mojo_bootstrap.cc b/chromium/ipc/ipc_mojo_bootstrap.cc
index 616382cb8f9c..9a9eeef84755 100644
--- src/3rdparty/chromium/ipc/ipc_mojo_bootstrap.cc.orig
+++ src/3rdparty/chromium/ipc/ipc_mojo_bootstrap.cc
@@ -702,13 +702,12 @@ class ChannelAssociatedGroupController
// handle.
DCHECK(!endpoint->client());
DCHECK(endpoint->peer_closed());
- MarkClosedAndMaybeRemove(endpoint);
+ MarkClosed(endpoint);
} else {
- MarkPeerClosedAndMaybeRemove(endpoint);
+ MarkPeerClosed(endpoint);
}
}
-
- DCHECK(endpoints_.empty());
+ endpoints_.clear();
GetMemoryDumpProvider().RemoveController(this);
}
@@ -755,15 +754,19 @@ class ChannelAssociatedGroupController
base::AutoLock locker(lock_);
encountered_error_ = true;
+ std::vector<uint32_t> endpoints_to_remove;
std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
Endpoint* endpoint = iter->second.get();
++iter;
- if (endpoint->client())
+ if (endpoint->client()) {
endpoints_to_notify.push_back(endpoint);
+ }
- MarkPeerClosedAndMaybeRemove(endpoint);
+ if (MarkPeerClosed(endpoint)) {
+ endpoints_to_remove.push_back(endpoint->id());
+ }
}
for (auto& endpoint : endpoints_to_notify) {
@@ -772,6 +775,10 @@ class ChannelAssociatedGroupController
if (endpoint->client())
NotifyEndpointOfError(endpoint.get(), false /* force_async */);
}
+
+ for (uint32_t id : endpoints_to_remove) {
+ endpoints_.erase(id);
+ }
}
void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
@@ -806,19 +813,33 @@ class ChannelAssociatedGroupController
NotifyEndpointOfError(endpoint, false /* force_async */);
}
- void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
+ // Marks `endpoint` as closed and returns true if and only if its peer was
+ // also already closed.
+ bool MarkClosed(Endpoint* endpoint) {
lock_.AssertAcquired();
endpoint->set_closed();
- if (endpoint->closed() && endpoint->peer_closed())
- endpoints_.erase(endpoint->id());
+ return endpoint->peer_closed();
}
- void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
+ // Marks `endpoint` as having a closed peer and returns true if and only if
+ // `endpoint` itself was also already closed.
+ bool MarkPeerClosed(Endpoint* endpoint) {
lock_.AssertAcquired();
endpoint->set_peer_closed();
endpoint->SignalSyncMessageEvent();
- if (endpoint->closed() && endpoint->peer_closed())
+ return endpoint->closed();
+ }
+
+ void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
+ if (MarkClosed(endpoint)) {
endpoints_.erase(endpoint->id());
+ }
+ }
+
+ void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
+ if (MarkPeerClosed(endpoint)) {
+ endpoints_.erase(endpoint->id());
+ }
}
Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {
From 4d095ba080045a255cb93ecadb9f3358fdc7cd80 Mon Sep 17 00:00:00 2001
From: Jordan Bayles <jophba@chromium.org>
Date: Fri, 6 Oct 2023 23:50:59 +0000
Subject: [PATCH] [Backport] CVE-2023-6510: Use after free in Media Capture
Manual backport of patch originally reviewed on
Fix UaF in WebContentsFrameTracker
This patch fixes a use-after-free by moving to a base::WeakPtr
instead of a raw_ptr. Looking at the callstack in the referenced bug, what is clearly happening is that the frame tracker is deleted AFTER the capture device. I believe that this is due to the MouseCursorOverlayController being deleted through the DeleteOnUIThread destructor, which, if you are already on the UI thread, is synchronous:
https://source.chromium.org/chromium/chromium/src/+/main:content/public/browser/browser_thread.h;l=141?q=BrowserThread::DeleteOnThread&ss=chromium%2Fchromium%2Fsrc
In comparison, the WebContentsFrameTracker is implemented using base::SequenceBound, which ends up calling an internal destruct method that ALWAYS posts back a task:
https://source.chromium.org/chromium/chromium/src/+/main:base/threading/sequence_bound_internal.h;drc=f5bdc89c7395ed24f1b8d196a3bdd6232d5bf771;l=122
So, this bug is ultimately caused by the simple fact that base::SequenceBound does NOT have an optimization to not post a deletion task if we are already running on that sequence. There may be a good followup task here to change either DeleteOnThread or base::SequenceBound to have the same behavior, however I think this change a good first step.
Bug: 1480152
Change-Id: Iee2d41e66b10403d6c78547bcbe84d2454236d5b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4908770
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1206698}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/523700
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../web_contents_video_capture_device.cc | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
index 0093df22c2b2..6100fe816784 100644
--- src/3rdparty/chromium/content/browser/media/capture/web_contents_video_capture_device.cc.orig
+++ src/3rdparty/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -41,7 +41,7 @@ class WebContentsVideoCaptureDevice::FrameTracker
int main_render_frame_id)
: device_(std::move(device)),
device_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- cursor_controller_(cursor_controller) {
+ cursor_controller_(cursor_controller->GetWeakPtr()) {
DCHECK(device_task_runner_);
DCHECK(cursor_controller_);
@@ -184,7 +184,9 @@ class WebContentsVideoCaptureDevice::FrameTracker
// Note: MouseCursorOverlayController runs on the UI thread. It's also
// important that SetTargetView() be called in the current stack while
// |native_view| is known to be a valid pointer. http://crbug.com/818679
- cursor_controller_->SetTargetView(native_view);
+ if (cursor_controller_) {
+ cursor_controller_->SetTargetView(native_view);
+ }
}
} else {
device_task_runner_->PostTask(
@@ -192,7 +194,9 @@ class WebContentsVideoCaptureDevice::FrameTracker
base::BindOnce(
&WebContentsVideoCaptureDevice::OnTargetPermanentlyLost,
device_));
- cursor_controller_->SetTargetView(gfx::NativeView());
+ if (cursor_controller_) {
+ cursor_controller_->SetTargetView(gfx::NativeView());
+ }
}
}
@@ -200,10 +204,11 @@ class WebContentsVideoCaptureDevice::FrameTracker
const base::WeakPtr<WebContentsVideoCaptureDevice> device_;
const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
- // Owned by FrameSinkVideoCaptureDevice. This will be valid for the life of
- // FrameTracker because the FrameTracker deleter task will be posted to the UI
- // thread before the MouseCursorOverlayController deleter task.
- MouseCursorOverlayController* const cursor_controller_;
+ // Owned by FrameSinkVideoCaptureDevice. This may only be accessed on the
+ // UI thread. This is not guaranteed to be valid and must be checked before
+ // use.
+ // https://crbug.com/1480152
+ const base::WeakPtr<MouseCursorOverlayController> cursor_controller_;
viz::FrameSinkId target_frame_sink_id_;
gfx::NativeView target_native_view_ = gfx::NativeView();
From 6a382d96ac3becf92f28f8549318390193da1ddd Mon Sep 17 00:00:00 2001
From: pthier <pthier@chromium.org>
Date: Tue, 24 Oct 2023 13:28:22 +0200
Subject: [PATCH] [Backport] Security bug 1488199 (1/2)
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/v8/v8/+/4971832:
[regexp] Fix stack check in native code when interrupt was requested
When an interrupt was requested at the time we hit the stack check, the
check to ensure we have enough space for local variables was skipped.
Bug: chromium:1488199
Change-Id: I95d82fe737420d2ef43c1ace35560cfd5860829b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4971832
Commit-Queue: Patrick Thier <pthier@chromium.org>
Reviewed-by: Jakob Linke <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#90560}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/523701
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../regexp/arm/regexp-macro-assembler-arm.cc | 22 +++++++-----
.../regexp/arm/regexp-macro-assembler-arm.h | 5 +--
.../arm64/regexp-macro-assembler-arm64.cc | 21 ++++++-----
.../arm64/regexp-macro-assembler-arm64.h | 6 ++--
.../ia32/regexp-macro-assembler-ia32.cc | 19 ++++++----
.../regexp/ia32/regexp-macro-assembler-ia32.h | 5 +--
.../v8/src/regexp/regexp-macro-assembler.cc | 5 +--
.../v8/src/regexp/regexp-macro-assembler.h | 2 +-
.../regexp/x64/regexp-macro-assembler-x64.cc | 35 ++++++++++++-------
.../regexp/x64/regexp-macro-assembler-x64.h | 4 +--
10 files changed, 78 insertions(+), 46 deletions(-)
diff --git a/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc b/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc
index 78b586e265d0..099fc62fa07b 100644
--- src/3rdparty/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc.orig
+++ src/3rdparty/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc
@@ -670,11 +670,13 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
__ mov(r0, Operand(stack_limit));
__ ldr(r0, MemOperand(r0));
__ sub(r0, sp, r0, SetCC);
+ Operand extra_space_for_variables(num_registers_ * kPointerSize);
+
// Handle it if the stack pointer is already below the stack limit.
__ b(ls, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
- __ cmp(r0, Operand(num_registers_ * kPointerSize));
+ __ cmp(r0, extra_space_for_variables);
__ b(hs, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
@@ -682,7 +684,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
__ jmp(&return_r0);
__ bind(&stack_limit_hit);
- CallCheckStackGuardState();
+ CallCheckStackGuardState(extra_space_for_variables);
__ cmp(r0, Operand::Zero());
// If returned value is non-zero, we exit with the returned value as result.
__ b(ne, &return_r0);
@@ -1048,16 +1050,18 @@ void RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) {
// Private methods:
-void RegExpMacroAssemblerARM::CallCheckStackGuardState() {
+void RegExpMacroAssemblerARM::CallCheckStackGuardState(Operand extra_space) {
DCHECK(!isolate()->IsGeneratingEmbeddedBuiltins());
DCHECK(!masm_->options().isolate_independent_code);
- __ PrepareCallCFunction(3);
+ __ PrepareCallCFunction(4);
+ // Extra space for variables to consider in stack check.
+ __ mov(arg_reg_4, extra_space);
// RegExp code frame pointer.
- __ mov(r2, frame_pointer());
+ __ mov(arg_reg3, frame_pointer());
// Code of self.
- __ mov(r1, Operand(masm_->CodeObject()));
+ __ mov(arg_reg2, Operand(masm_->CodeObject()));
// We need to make room for the return address on the stack.
int stack_alignment = base::OS::ActivationFrameAlignment();
@@ -1101,7 +1105,8 @@ static T* frame_entry_address(Address re_frame, int frame_offset) {
int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
Address raw_code,
- Address re_frame) {
+ Address re_frame,
+ uintptr_t extra_space) {
Code re_code = Code::cast(Object(raw_code));
return NativeRegExpMacroAssembler::CheckStackGuardState(
frame_entry<Isolate*>(re_frame, kIsolate),
@@ -1110,7 +1115,8 @@ int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
return_address, re_code,
frame_entry_address<Address>(re_frame, kInputString),
frame_entry_address<const byte*>(re_frame, kInputStart),
- frame_entry_address<const byte*>(re_frame, kInputEnd));
+ frame_entry_address<const byte*>(re_frame, kInputEnd),
+ extra_space);
}
diff --git a/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.h b/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.h
index 910e5c46079a..114120755fcb 100644
--- src/3rdparty/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.h.orig
+++ src/3rdparty/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.h
@@ -89,7 +89,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
// returning.
// {raw_code} is an Address because this is called via ExternalReference.
static int CheckStackGuardState(Address* return_address, Address raw_code,
- Address re_frame);
+ Address re_frame, uintptr_t extra_space);
private:
// Offsets from frame_pointer() of function parameters and stored registers.
@@ -134,7 +134,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
// Generate a call to CheckStackGuardState.
- void CallCheckStackGuardState();
+ void CallCheckStackGuardState(
+ Operand extra_space_for_variables = Operand::Zero());
// The ebp-relative location of a regexp register.
MemOperand register_location(int register_index);
diff --git a/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc b/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc
index ac33f8631ffe..1e5342dd42e5 100644
--- src/3rdparty/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc.orig
+++ src/3rdparty/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc
@@ -781,13 +781,14 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
__ Mov(x10, stack_limit);
__ Ldr(x10, MemOperand(x10));
__ Subs(x10, sp, x10);
+ Operand extra_space_for_variables(num_wreg_to_allocate * kWRegSize);
// Handle it if the stack pointer is already below the stack limit.
__ B(ls, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
- __ Cmp(x10, num_wreg_to_allocate * kWRegSize);
+ __ Cmp(x10, extra_space_for_variables);
__ B(hs, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
@@ -796,7 +797,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
__ B(&return_w0);
__ Bind(&stack_limit_hit);
- CallCheckStackGuardState(x10);
+ CallCheckStackGuardState(x10, extra_space_for_variables);
// If returned value is non-zero, we exit with the returned value as result.
__ Cbnz(w0, &return_w0);
@@ -1332,13 +1333,14 @@ static T* frame_entry_address(Address re_frame, int frame_offset) {
int RegExpMacroAssemblerARM64::CheckStackGuardState(
Address* return_address, Address raw_code, Address re_frame,
- int start_index, const byte** input_start, const byte** input_end) {
+ int start_index, const byte** input_start, const byte** input_end,
+ uintptr_t extra_space) {
Code re_code = Code::cast(Object(raw_code));
return NativeRegExpMacroAssembler::CheckStackGuardState(
frame_entry<Isolate*>(re_frame, kIsolate), start_index,
static_cast<RegExp::CallOrigin>(frame_entry<int>(re_frame, kDirectCall)),
return_address, re_code, frame_entry_address<Address>(re_frame, kInput),
- input_start, input_end);
+ input_start, input_end, extra_space);
}
@@ -1357,21 +1359,24 @@ void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset,
// Private methods:
-void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch) {
+void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch,
+ Operand extra_space) {
DCHECK(!isolate()->IsGeneratingEmbeddedBuiltins());
DCHECK(!masm_->options().isolate_independent_code);
// Allocate space on the stack to store the return address. The
// CheckStackGuardState C++ function will override it if the code
- // moved. Allocate extra space for 2 arguments passed by pointers.
- // AAPCS64 requires the stack to be 16 byte aligned.
+ // moved. Allocate extra space for 3 arguments (2 for input start/end and 1
+ // for gap). AAPCS64 requires the stack to be 16 byte aligned.
int alignment = masm_->ActivationFrameAlignment();
DCHECK_EQ(alignment % 16, 0);
int align_mask = (alignment / kXRegSize) - 1;
- int xreg_to_claim = (3 + align_mask) & ~align_mask;
+ int xreg_to_claim = (4 + align_mask) & ~align_mask;
__ Claim(xreg_to_claim);
+ __ Mov(x0, extra_space);
+ __ Poke(x0, 3 * kSystemPointerSize);
// CheckStackGuardState needs the end and start addresses of the input string.
__ Poke(input_end(), 2 * kSystemPointerSize);
__ Add(x5, sp, 2 * kSystemPointerSize);
diff --git a/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.h b/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.h
index aeb49aa9fff3..e4c4b0ac34f3 100644
--- src/3rdparty/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.h.orig
+++ src/3rdparty/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.h
@@ -97,7 +97,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
static int CheckStackGuardState(Address* return_address, Address raw_code,
Address re_frame, int start_offset,
const byte** input_start,
- const byte** input_end);
+ const byte** input_end,
+ uintptr_t extra_space);
private:
// Above the frame pointer - Stored registers and stack passed parameters.
@@ -145,7 +146,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
void CheckStackLimit();
// Generate a call to CheckStackGuardState.
- void CallCheckStackGuardState(Register scratch);
+ void CallCheckStackGuardState(Register scratch,
+ Operand extra_space = Operand(0));
// Location of a 32 bit position register.
MemOperand register_location(int register_index);
diff --git a/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.cc b/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.cc
index 2135e977a742..d5fbd960675e 100644
--- src/3rdparty/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.cc.orig
+++ src/3rdparty/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.cc
@@ -700,11 +700,13 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
ExternalReference::address_of_jslimit(isolate());
__ mov(ecx, esp);
__ sub(ecx, StaticVariable(stack_limit));
+ Immediate extra_space_for_variables(num_registers_ * kSystemPointerSize);
+
// Handle it if the stack pointer is already below the stack limit.
__ j(below_equal, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
- __ cmp(ecx, num_registers_ * kSystemPointerSize);
+ __ cmp(ecx, extra_space_for_variables);
__ j(above_equal, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
@@ -712,7 +714,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ jmp(&return_eax);
__ bind(&stack_limit_hit);
- CallCheckStackGuardState(ebx);
+ CallCheckStackGuardState(ebx, extra_space_for_variables);
__ or_(eax, eax);
// If returned value is non-zero, we exit with the returned value as result.
__ j(not_zero, &return_eax);
@@ -1080,9 +1082,12 @@ void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
// Private methods:
-void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
- static const int num_arguments = 3;
+void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch,
+ Immediate extra_space) {
+ static const int num_arguments = 4;
__ PrepareCallCFunction(num_arguments, scratch);
+ // Extra space for variables.
+ __ mov(Operand(esp, 3 * kSystemPointerSize), extra_space);
// RegExp code frame pointer.
__ mov(Operand(esp, 2 * kSystemPointerSize), ebp);
// Code of self.
@@ -1113,7 +1118,8 @@ static T* frame_entry_address(Address re_frame, int frame_offset) {
int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
Address raw_code,
- Address re_frame) {
+ Address re_frame,
+ uintptr_t extra_space) {
Code re_code = Code::cast(Object(raw_code));
return NativeRegExpMacroAssembler::CheckStackGuardState(
frame_entry<Isolate*>(re_frame, kIsolate),
@@ -1122,7 +1128,8 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
return_address, re_code,
frame_entry_address<Address>(re_frame, kInputString),
frame_entry_address<const byte*>(re_frame, kInputStart),
- frame_entry_address<const byte*>(re_frame, kInputEnd));
+ frame_entry_address<const byte*>(re_frame, kInputEnd),
+ extra_space);
}
diff --git a/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.h b/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.h
index a30bff29a15c..620e7fb2982e 100644
--- src/3rdparty/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.h.orig
+++ src/3rdparty/chromium/v8/src/regexp/ia32/regexp-macro-assembler-ia32.h
@@ -88,7 +88,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
// returning.
// {raw_code} is an Address because this is called via ExternalReference.
static int CheckStackGuardState(Address* return_address, Address raw_code,
- Address re_frame);
+ Address re_frame, uintptr_t extra_space);
private:
Operand StaticVariable(const ExternalReference& ext);
@@ -133,7 +133,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
void CheckStackLimit();
// Generate a call to CheckStackGuardState.
- void CallCheckStackGuardState(Register scratch);
+ void CallCheckStackGuardState(Register scratch,
+ Immediate extra_space = Immediate(0));
// The ebp-relative location of a regexp register.
Operand register_location(int register_index);
diff --git a/chromium/v8/src/regexp/regexp-macro-assembler.cc b/chromium/v8/src/regexp/regexp-macro-assembler.cc
index cf4346309eb2..009027c10398 100644
--- src/3rdparty/chromium/v8/src/regexp/regexp-macro-assembler.cc.orig
+++ src/3rdparty/chromium/v8/src/regexp/regexp-macro-assembler.cc
@@ -168,14 +168,15 @@ bool NativeRegExpMacroAssembler::CanReadUnaligned() {
int NativeRegExpMacroAssembler::CheckStackGuardState(
Isolate* isolate, int start_index, RegExp::CallOrigin call_origin,
Address* return_address, Code re_code, Address* subject,
- const byte** input_start, const byte** input_end) {
+ const byte** input_start, const byte** input_end,
+ uintptr_t gap) {
DisallowHeapAllocation no_gc;
Address old_pc = PointerAuthentication::AuthenticatePC(return_address, 0);
DCHECK_LE(re_code.raw_instruction_start(), old_pc);
DCHECK_LE(old_pc, re_code.raw_instruction_end());
StackLimitCheck check(isolate);
- bool js_has_overflowed = check.JsHasOverflowed();
+ bool js_has_overflowed = check.JsHasOverflowed(gap);
if (call_origin == RegExp::CallOrigin::kFromJs) {
// Direct calls from JavaScript can be interrupted in two ways:
diff --git a/chromium/v8/src/regexp/regexp-macro-assembler.h b/chromium/v8/src/regexp/regexp-macro-assembler.h
index 52465610cb66..da233d3c73df 100644
--- src/3rdparty/chromium/v8/src/regexp/regexp-macro-assembler.h.orig
+++ src/3rdparty/chromium/v8/src/regexp/regexp-macro-assembler.h
@@ -261,7 +261,7 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
RegExp::CallOrigin call_origin,
Address* return_address, Code re_code,
Address* subject, const byte** input_start,
- const byte** input_end);
+ const byte** input_end, uintptr_t gap);
// Byte map of one byte characters with a 0xff if the character is a word
// character (digit, letter or underscore) and 0x00 otherwise.
diff --git a/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.cc b/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.cc
index da0397689fba..6ae1114f24ef 100644
--- src/3rdparty/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.cc.orig
+++ src/3rdparty/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.cc
@@ -736,11 +736,13 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
__ movq(rcx, rsp);
__ Move(kScratchRegister, stack_limit);
__ subq(rcx, Operand(kScratchRegister, 0));
+ Immediate extra_space_for_variables(num_registers_ * kSystemPointerSize);
+
// Handle it if the stack pointer is already below the stack limit.
__ j(below_equal, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
- __ cmpq(rcx, Immediate(num_registers_ * kSystemPointerSize));
+ __ cmpq(rcx, extra_space_for_variables);
__ j(above_equal, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
@@ -749,7 +751,8 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
__ bind(&stack_limit_hit);
__ Move(code_object_pointer(), masm_.CodeObject());
- CallCheckStackGuardState(); // Preserves no registers beside rbp and rsp.
+ // CallCheckStackGuardState preserves no registers beside rbp and rsp.
+ CallCheckStackGuardState(extra_space_for_variables);
__ testq(rax, rax);
// If returned value is non-zero, we exit with the returned value as result.
__ j(not_zero, &return_rax);
@@ -1147,27 +1150,31 @@ void RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) {
// Private methods:
-void RegExpMacroAssemblerX64::CallCheckStackGuardState() {
+void RegExpMacroAssemblerX64::CallCheckStackGuardState(Immediate extra_space) {
// This function call preserves no register values. Caller should
// store anything volatile in a C call or overwritten by this function.
- static const int num_arguments = 3;
+ static const int num_arguments = 4;
__ PrepareCallCFunction(num_arguments);
#ifdef V8_TARGET_OS_WIN
- // Second argument: Code of self. (Do this before overwriting r8).
- __ movq(rdx, code_object_pointer());
+ // Fourth argument: Extra space for variables.
+ __ movq(arg_reg_4, extra_space);
+ // Second argument: Code of self. (Do this before overwriting r8 (arg_reg_3)).
+ __ movq(arg_reg_2, code_object_pointer());
// Third argument: RegExp code frame pointer.
- __ movq(r8, rbp);
+ __ movq(arg_reg_3, rbp);
// First argument: Next address on the stack (will be address of
// return address).
- __ leaq(rcx, Operand(rsp, -kSystemPointerSize));
+ __ leaq(arg_reg_1, Operand(rsp, -kSystemPointerSize));
#else
+ // Fourth argument: Extra space for variables.
+ __ movq(arg_reg_4, extra_space);
// Third argument: RegExp code frame pointer.
- __ movq(rdx, rbp);
+ __ movq(arg_reg_3, rbp);
// Second argument: Code of self.
- __ movq(rsi, code_object_pointer());
+ __ movq(arg_reg_2, code_object_pointer());
// First argument: Next address on the stack (will be address of
// return address).
- __ leaq(rdi, Operand(rsp, -kSystemPointerSize));
+ __ leaq(arg_reg_1, Operand(rsp, -kSystemPointerSize));
#endif
ExternalReference stack_check =
ExternalReference::re_check_stack_guard_state(isolate());
@@ -1189,7 +1196,8 @@ static T* frame_entry_address(Address re_frame, int frame_offset) {
int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
Address raw_code,
- Address re_frame) {
+ Address re_frame,
+ uintptr_t extra_space) {
Code re_code = Code::cast(Object(raw_code));
return NativeRegExpMacroAssembler::CheckStackGuardState(
frame_entry<Isolate*>(re_frame, kIsolate),
@@ -1198,7 +1206,8 @@ int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
return_address, re_code,
frame_entry_address<Address>(re_frame, kInputString),
frame_entry_address<const byte*>(re_frame, kInputStart),
- frame_entry_address<const byte*>(re_frame, kInputEnd));
+ frame_entry_address<const byte*>(re_frame, kInputEnd),
+ extra_space);
}
diff --git a/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.h b/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.h
index ea4d45edba83..6e5dcd18c286 100644
--- src/3rdparty/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.h.orig
+++ src/3rdparty/chromium/v8/src/regexp/x64/regexp-macro-assembler-x64.h
@@ -82,7 +82,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
// returning.
// {raw_code} is an Address because this is called via ExternalReference.
static int CheckStackGuardState(Address* return_address, Address raw_code,
- Address re_frame);
+ Address re_frame, uintptr_t extra_space);
private:
// Offsets from rbp of function parameters and stored registers.
@@ -166,7 +166,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
void CheckStackLimit();
// Generate a call to CheckStackGuardState.
- void CallCheckStackGuardState();
+ void CallCheckStackGuardState(Immediate extra_space = Immediate(0));
// The rbp-relative location of a regexp register.
Operand register_location(int register_index);
From a3a63cf72f11a9e1a40fd076dea0ce8f532251ba Mon Sep 17 00:00:00 2001
From: pthier <pthier@chromium.org>
Date: Mon, 30 Oct 2023 11:59:09 +0100
Subject: [PATCH] [Backport] Security bug 1488199 (2/2)
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/v8/v8/+/4987306:
[regexp][arm64] Fix stack check extra space argument
Pass argument in register instead of the stack.
Bug: chromium:1488199, v8:14415
Change-Id: Ic9967c9f2ca5da1981a0138ddb5f0335ab7f1425
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4987306
Commit-Queue: Patrick Thier <pthier@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#90669}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/523702
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc b/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc
index 1e5342dd42e..aaab0c52344 100644
--- src/3rdparty/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc.orig
+++ src/3rdparty/chromium/v8/src/regexp/arm64/regexp-macro-assembler-arm64.cc
@@ -1366,17 +1366,16 @@ void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch,
// Allocate space on the stack to store the return address. The
// CheckStackGuardState C++ function will override it if the code
- // moved. Allocate extra space for 3 arguments (2 for input start/end and 1
- // for gap). AAPCS64 requires the stack to be 16 byte aligned.
+ // moved. Allocate extra space for 2 arguments passed by pointers.
+ // AAPCS64 requires the stack to be 16 byte aligned.
int alignment = masm_->ActivationFrameAlignment();
DCHECK_EQ(alignment % 16, 0);
int align_mask = (alignment / kXRegSize) - 1;
- int xreg_to_claim = (4 + align_mask) & ~align_mask;
+ int xreg_to_claim = (3 + align_mask) & ~align_mask;
__ Claim(xreg_to_claim);
- __ Mov(x0, extra_space);
- __ Poke(x0, 3 * kSystemPointerSize);
+ __ Mov(x6, extra_space);
// CheckStackGuardState needs the end and start addresses of the input string.
__ Poke(input_end(), 2 * kSystemPointerSize);
__ Add(x5, sp, 2 * kSystemPointerSize);
From 7eb931bc199e72fbf95aed22c9dd370269862c6c Mon Sep 17 00:00:00 2001
From: Michal Klocek <michal.klocek@qt.io>
Date: Mon, 8 Jan 2024 11:23:07 +0100
Subject: [PATCH] [Backport] CVE-2023-6345: Integer overflow in Skia
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cherry-pick of patch originally reviewed on
https://skia-review.googlesource.com/c/skia/+/782936:
Avoid combining extremely large meshes.
Bug: chromium:1505053
Fixes: QTBUG-120589
Change-Id: I42f2ff872bbf054686ec7af0cc85ff63055fcfbf
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/528729
Reviewed-by: Michael Brüning <michael.bruning@qt.io>
---
chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp
index 0a80e674325f..e50293b4dfe9 100644
--- src/3rdparty/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp
+++ src/3rdparty/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -757,7 +757,11 @@ GrOp::CombineResult DrawVerticesOp::onCombineIfPossible(GrOp* t, GrRecordingCont
return CombineResult::kCannotCombine;
}
- if (fVertexCount + that->fVertexCount > SkTo<int>(UINT16_MAX)) {
+ if (fVertexCount > INT32_MAX - that->fVertexCount) {
+ return CombineResult::kCannotCombine;
+ }
+
+ if (fVertexCount > SkTo<int>(UINT16_MAX) - that->fVertexCount) {
return CombineResult::kCannotCombine;
}
From 31c7c9445955762102fdcd04e71da6114e1fcb4c Mon Sep 17 00:00:00 2001
From: Zakhar Voit <voit@google.com>
Date: Thu, 14 Dec 2023 11:11:43 +0000
Subject: [PATCH] [Backport] CVE-2023-6702: Type Confusion in V8
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/v8/v8/+/5110982:
[M114-LTS][promises, async stack traces] Fix the case when the closure has run
M114 changes:
- replace IsNativeContext(*context) by context->IsNativeContext()
We were using the closure pointing to NativeContext as a marker that the
closure has run, but async stack trace code was confused about it.
(cherry picked from commit bde3d360097607f36cd1d17cbe8412b84eae0a7f)
Bug: chromium:1501326
Change-Id: I30d438f3b2e3fdd7562ea9a79dde4561ce9b0083
Cr-Original-Commit-Position: refs/heads/main@{#90949}
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5110982
Commit-Queue: Marja Hölttä <marja@chromium.org>
Auto-Submit: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/branch-heads/12.0@{#18}
Cr-Branched-From: ed7b4caf1fb8184ad9e24346c84424055d4d430a-refs/heads/12.0.267@{#1}
Cr-Branched-From: 210e75b19db4352c9b78dce0bae11c2dc3077df4-refs/heads/main@{#90651}
(cherry picked from commit cbd09b2ca928f1fd929ef52e173aa81213e38cb8)
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/526232
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
chromium/v8/src/execution/isolate.cc | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/chromium/v8/src/execution/isolate.cc b/chromium/v8/src/execution/isolate.cc
index c1c3bd1b24a6..99b851ef96d7 100644
--- src/3rdparty/chromium/v8/src/execution/isolate.cc
+++ src/3rdparty/chromium/v8/src/execution/isolate.cc
@@ -944,7 +944,13 @@ void CaptureAsyncStackTrace(Isolate* isolate, Handle<JSPromise> promise,
builder->AppendPromiseCombinatorFrame(function, combinator,
FrameArray::kIsPromiseAll, context);
- // Now peak into the Promise.all() resolve element context to
+ if (context->IsNativeContext()) {
+ // NativeContext is used as a marker that the closure was already
+ // called. We can't access the reject element context any more.
+ return;
+ }
+
+ // Now peek into the Promise.all() resolve element context to
// find the promise capability that's being resolved when all
// the concurrent promises resolve.
int const index =
@@ -963,7 +969,13 @@ void CaptureAsyncStackTrace(Isolate* isolate, Handle<JSPromise> promise,
builder->AppendPromiseCombinatorFrame(function, combinator,
FrameArray::kIsPromiseAny, context);
- // Now peak into the Promise.any() reject element context to
+ if (context->IsNativeContext()) {
+ // NativeContext is used as a marker that the closure was already
+ // called. We can't access the reject element context any more.
+ return;
+ }
+
+ // Now peek into the Promise.any() reject element context to
// find the promise capability that's being resolved when any of
// the concurrent promises resolve.
int const index = PromiseBuiltins::kPromiseAnyRejectElementCapabilitySlot;
From 73c9c09a8b314b8c66bbe3d2648d6bfe18d5d4a8 Mon Sep 17 00:00:00 2001
From: Kai Ninomiya <kainino@chromium.org>
Date: Wed, 29 Nov 2023 17:44:48 +0000
Subject: [PATCH] [Backport] Security bug 1505632
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5069480:
Fix reinit order in ContextProviderCommandBuffer::BindToCurrentSequence
See comments for explanation.
Bug: 1505632
Change-Id: I0f43821a9708af91303048332e9fae5e100deee5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5069480
Reviewed-by: Saifuddin Hitawala <hitawala@chromium.org>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Brendon Tiszka <tiszka@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1230735}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/526233
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../gpu/context_provider_command_buffer.cc | 24 +++++++++----
.../cpp/gpu/context_provider_command_buffer.h | 34 ++++++++++++++++---
2 files changed, 47 insertions(+), 11 deletions(-)
diff --git a/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
index e8b9ff4983d4..d79b97fd3748 100644
--- src/3rdparty/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
+++ src/3rdparty/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
@@ -164,13 +164,13 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
}
// The transfer buffer is used to serialize Dawn commands
- transfer_buffer_ =
+ auto transfer_buffer =
std::make_unique<gpu::TransferBuffer>(webgpu_helper.get());
// The WebGPUImplementation exposes the WebGPUInterface, as well as the
// gpu::ContextSupport interface.
auto webgpu_impl = std::make_unique<gpu::webgpu::WebGPUImplementation>(
- webgpu_helper.get(), transfer_buffer_.get(), command_buffer_.get());
+ webgpu_helper.get(), transfer_buffer.get(), command_buffer_.get());
bind_result_ = webgpu_impl->Initialize(memory_limits_);
if (bind_result_ != gpu::ContextResult::kSuccess) {
DLOG(ERROR) << "Failed to initialize WebGPUImplementation.";
@@ -182,8 +182,11 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
std::string unique_context_name =
base::StringPrintf("%s-%p", type_name.c_str(), webgpu_impl.get());
+ // IMPORTANT: These hold raw_ptrs to each other, so must be set together.
+ // See note in the header (and keep it up to date if things change).
impl_ = webgpu_impl.get();
webgpu_interface_ = std::move(webgpu_impl);
+ transfer_buffer_ = std::move(transfer_buffer);
helper_ = std::move(webgpu_helper);
} else if (attributes_.enable_raster_interface &&
!attributes_.enable_gles2_interface &&
@@ -201,14 +204,14 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
}
// The transfer buffer is used to copy resources between the client
// process and the GPU process.
- transfer_buffer_ =
+ auto transfer_buffer =
std::make_unique<gpu::TransferBuffer>(raster_helper.get());
// The RasterImplementation exposes the RasterInterface, as well as the
// gpu::ContextSupport interface.
DCHECK(channel_);
auto raster_impl = std::make_unique<gpu::raster::RasterImplementation>(
- raster_helper.get(), transfer_buffer_.get(),
+ raster_helper.get(), transfer_buffer.get(),
attributes_.bind_generates_resource,
attributes_.lose_context_when_out_of_memory, command_buffer_.get(),
channel_->image_decode_accelerator_proxy());
@@ -225,8 +228,11 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
raster_impl->TraceBeginCHROMIUM("gpu_toplevel",
unique_context_name.c_str());
+ // IMPORTANT: These hold raw_ptrs to each other, so must be set together.
+ // See note in the header (and keep it up to date if things change).
impl_ = raster_impl.get();
raster_interface_ = std::move(raster_impl);
+ transfer_buffer_ = std::move(transfer_buffer);
helper_ = std::move(raster_helper);
} else {
// The GLES2 helper writes the command buffer protocol.
@@ -241,7 +247,7 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
// The transfer buffer is used to copy resources between the client
// process and the GPU process.
- transfer_buffer_ =
+ auto transfer_buffer =
std::make_unique<gpu::TransferBuffer>(gles2_helper.get());
// The GLES2Implementation exposes the OpenGLES2 API, as well as the
@@ -254,13 +260,13 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
// we only use it if grcontext_support was requested.
gles2_impl = std::make_unique<
skia_bindings::GLES2ImplementationWithGrContextSupport>(
- gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer_.get(),
+ gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer.get(),
attributes_.bind_generates_resource,
attributes_.lose_context_when_out_of_memory,
support_client_side_arrays, command_buffer_.get());
} else {
gles2_impl = std::make_unique<gpu::gles2::GLES2Implementation>(
- gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer_.get(),
+ gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer.get(),
attributes_.bind_generates_resource,
attributes_.lose_context_when_out_of_memory,
support_client_side_arrays, command_buffer_.get());
@@ -271,8 +277,11 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
return bind_result_;
}
+ // IMPORTANT: These hold raw_ptrs to each other, so must be set together.
+ // See note in the header (and keep it up to date if things change).
impl_ = gles2_impl.get();
gles2_impl_ = std::move(gles2_impl);
+ transfer_buffer_ = std::move(transfer_buffer);
helper_ = std::move(gles2_helper);
}
@@ -306,6 +315,7 @@ gpu::ContextResult ContextProviderCommandBuffer::BindToCurrentThread() {
switches::kEnableGpuClientTracing)) {
// This wraps the real GLES2Implementation and we should always use this
// instead when it's present.
+ // IMPORTANT: This holds a raw_ptr to gles2_impl_.
trace_impl_ = std::make_unique<gpu::gles2::GLES2TraceImplementation>(
gles2_impl_.get());
gl = trace_impl_.get();
diff --git a/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
index 22d80baf765b..9a867177048e 100644
--- src/3rdparty/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
+++ src/3rdparty/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -156,18 +156,44 @@ class ContextProviderCommandBuffer
// associated shared images are destroyed.
std::unique_ptr<gpu::ClientSharedImageInterface> shared_image_interface_;
- base::Lock context_lock_; // Referenced by command_buffer_.
+ //////////////////////////////////////////////////////////////////////////////
+ // IMPORTANT NOTE: All of the objects in this block are part of a complex //
+ // graph of raw pointers (holder or pointee of various raw_ptrs). They are //
+ // defined in topological order: only later items point to earlier items. //
+ // - When writing any member, always ensure its pointers to earlier members
+ // are guaranteed to stay alive.
+ // - When clearing OR overwriting any member, always ensure objects that
+ // point to it have already been cleared.
+ // - The topological order of definitions guarantees that the
+ // destructors will be called in the correct order (bottom to top).
+ // - When overwriting multiple members, similarly do so in reverse order.
+ //
+ // Please note these comments are likely not to stay perfectly up-to-date.
+
+ base::Lock context_lock_;
+ // Points to the context_lock_ field of `this`.
std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
+
+ // Points to command_buffer_.
std::unique_ptr<gpu::CommandBufferHelper> helper_;
+ // Points to helper_.
std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
- // Owned by either gles2_impl_ or raster_interface_, not both.
- gpu::ImplementationBase* impl_;
+ // Points to transfer_buffer_, helper_, and command_buffer_.
std::unique_ptr<gpu::gles2::GLES2Implementation> gles2_impl_;
+ // Points to gles2_impl_.
std::unique_ptr<gpu::gles2::GLES2TraceImplementation> trace_impl_;
- std::unique_ptr<gpu::raster::RasterInterface> raster_interface_;
+ // Points to transfer_buffer_, helper_, and command_buffer_.
+ std::unique_ptr<gpu::raster::RasterInterface> raster_interface_;
+ // Points to transfer_buffer_, helper_, and command_buffer_.
std::unique_ptr<gpu::webgpu::WebGPUInterface> webgpu_interface_;
+ // END IMPORTANT NOTE //
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Owned by either gles2_impl_ or raster_interface_, not both.
+ gpu::ImplementationBase* impl_;
+
std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
#if BUILDFLAG(SKIA_USE_DAWN)
std::unique_ptr<skia_bindings::GrContextForWebGPUInterface>
From 2d8ce130db72ce75e2ca8b51f3c32938fbff9143 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20Br=C3=BCning?= <michael.bruning@qt.io>
Date: Mon, 8 Jan 2024 15:39:03 +0100
Subject: [PATCH] Fixup: [Backport] Security bug 1505632
Change-Id: I8af12a1fecededb373145fd89362e08b030f1d7f
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/528821
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../viz/public/cpp/gpu/context_provider_command_buffer.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
index 9a867177048..0ac70dae7e9 100644
--- src/3rdparty/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
+++ src/3rdparty/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -192,7 +192,7 @@ class ContextProviderCommandBuffer
//////////////////////////////////////////////////////////////////////////////
// Owned by either gles2_impl_ or raster_interface_, not both.
- gpu::ImplementationBase* impl_;
+ gpu::ImplementationBase* impl_ = nullptr;
std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
#if BUILDFLAG(SKIA_USE_DAWN)
From c8088aea77818f87d42f709ddcb743b907c38e9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20Br=C3=BCning?= <michael.bruning@qt.io>
Date: Sun, 14 Jan 2024 23:48:08 +0100
Subject: [PATCH] Fixup: [Backport] Security bug 1488199
Add register aliases following respective platform calling
conventions. Also fix a typo.
Change-Id: I8f844cd4db35393580f2a0adae6a4095584087a5
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/530618
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
---
chromium/v8/src/codegen/arm/register-arm.h | 6 ++++++
chromium/v8/src/codegen/arm64/register-arm64.h | 6 ++++++
chromium/v8/src/codegen/mips64/register-mips64.h | 6 ++++++
chromium/v8/src/codegen/ppc/register-ppc.h | 6 ++++++
chromium/v8/src/codegen/s390/register-s390.h | 6 ++++++
chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc | 4 ++--
6 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/chromium/v8/src/codegen/arm/register-arm.h b/chromium/v8/src/codegen/arm/register-arm.h
index 6cb6c602c254..8deddc5804b1 100644
--- src/3rdparty/chromium/v8/src/codegen/arm/register-arm.h
+++ src/3rdparty/chromium/v8/src/codegen/arm/register-arm.h
@@ -119,6 +119,12 @@ GENERAL_REGISTERS(DECLARE_REGISTER)
#undef DECLARE_REGISTER
constexpr Register no_reg = Register::no_reg();
+// ARM calling convention
+constexpr Register arg_reg_1 = r0;
+constexpr Register arg_reg_2 = r1;
+constexpr Register arg_reg_3 = r2;
+constexpr Register arg_reg_4 = r3;
+
constexpr bool kPadArguments = false;
constexpr bool kSimpleFPAliasing = false;
constexpr bool kSimdMaskRegisters = false;
diff --git a/chromium/v8/src/codegen/arm64/register-arm64.h b/chromium/v8/src/codegen/arm64/register-arm64.h
index fbbb0a18dadf..06026a065bbf 100644
--- src/3rdparty/chromium/v8/src/codegen/arm64/register-arm64.h
+++ src/3rdparty/chromium/v8/src/codegen/arm64/register-arm64.h
@@ -482,6 +482,12 @@ ALIAS_REGISTER(VRegister, fp_scratch2, d31);
#undef ALIAS_REGISTER
+// Arm64 calling convention
+constexpr Register arg_reg_1 = x0;
+constexpr Register arg_reg_2 = x1;
+constexpr Register arg_reg_3 = x2;
+constexpr Register arg_reg_4 = x3;
+
// AreAliased returns true if any of the named registers overlap. Arguments set
// to NoReg are ignored. The system stack pointer may be specified.
V8_EXPORT_PRIVATE bool AreAliased(
diff --git a/chromium/v8/src/codegen/mips64/register-mips64.h b/chromium/v8/src/codegen/mips64/register-mips64.h
index d7b45eda3838..05aba9fcbd2f 100644
--- src/3rdparty/chromium/v8/src/codegen/mips64/register-mips64.h
+++ src/3rdparty/chromium/v8/src/codegen/mips64/register-mips64.h
@@ -362,6 +362,12 @@ DEFINE_REGISTER_NAMES(FPURegister, DOUBLE_REGISTERS)
DEFINE_REGISTER_NAMES(MSARegister, SIMD128_REGISTERS)
// Give alias names to registers for calling conventions.
+
+constexpr Register arg_reg_1 = a0;
+constexpr Register arg_reg_2 = a1;
+constexpr Register arg_reg_3 = a2;
+constexpr Register arg_reg_4 = a3;
+
constexpr Register kReturnRegister0 = v0;
constexpr Register kReturnRegister1 = v1;
constexpr Register kReturnRegister2 = a0;
diff --git a/chromium/v8/src/codegen/ppc/register-ppc.h b/chromium/v8/src/codegen/ppc/register-ppc.h
index eded9622c4cc..352b95192023 100644
--- src/3rdparty/chromium/v8/src/codegen/ppc/register-ppc.h
+++ src/3rdparty/chromium/v8/src/codegen/ppc/register-ppc.h
@@ -209,6 +209,12 @@ constexpr Register kConstantPoolRegister = r28; // Constant pool.
constexpr Register kRootRegister = r29; // Roots array pointer.
constexpr Register cp = r30; // JavaScript context pointer.
+// PPC64 calling convention
+constexpr Register arg_reg_1 = r3;
+constexpr Register arg_reg_2 = r4;
+constexpr Register arg_reg_3 = r5;
+constexpr Register arg_reg_4 = r6;
+
constexpr bool kPadArguments = false;
constexpr bool kSimpleFPAliasing = true;
constexpr bool kSimdMaskRegisters = false;
diff --git a/chromium/v8/src/codegen/s390/register-s390.h b/chromium/v8/src/codegen/s390/register-s390.h
index 009248a65ca0..6904802d0150 100644
--- src/3rdparty/chromium/v8/src/codegen/s390/register-s390.h
+++ src/3rdparty/chromium/v8/src/codegen/s390/register-s390.h
@@ -167,6 +167,12 @@ constexpr Register no_reg = Register::no_reg();
constexpr Register kRootRegister = r10; // Roots array pointer.
constexpr Register cp = r13; // JavaScript context pointer.
+// s390x calling convention
+constexpr Register arg_reg_1 = r2;
+constexpr Register arg_reg_2 = r3;
+constexpr Register arg_reg_3 = r4;
+constexpr Register arg_reg_4 = r5;
+
constexpr bool kPadArguments = false;
constexpr bool kSimpleFPAliasing = true;
constexpr bool kSimdMaskRegisters = false;
diff --git a/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc b/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc
index 099fc62fa07b..5580b24308a7 100644
--- src/3rdparty/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc
+++ src/3rdparty/chromium/v8/src/regexp/arm/regexp-macro-assembler-arm.cc
@@ -1059,9 +1059,9 @@ void RegExpMacroAssemblerARM::CallCheckStackGuardState(Operand extra_space) {
// Extra space for variables to consider in stack check.
__ mov(arg_reg_4, extra_space);
// RegExp code frame pointer.
- __ mov(arg_reg3, frame_pointer());
+ __ mov(arg_reg_3, frame_pointer());
// Code of self.
- __ mov(arg_reg2, Operand(masm_->CodeObject()));
+ __ mov(arg_reg_2, Operand(masm_->CodeObject()));
// We need to make room for the return address on the stack.
int stack_alignment = base::OS::ActivationFrameAlignment();
From aac73f3a715655476ce5b347a9614d1ca0ba9b93 Mon Sep 17 00:00:00 2001
From: Shahbaz Youssefi <syoussefi@chromium.org>
Date: Tue, 5 Dec 2023 13:36:53 -0500
Subject: [PATCH] [Backport] CVE-2024-0222: Use after free in ANGLE
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/angle/angle/+/5143829:
M120: Vulkan: Don't crash when glCopyTexImage2D redefines itself
The Vulkan backend marks a level being redefined as such before doing
the copy. If a single-level texture was being redefined, it releases it
so it can be immediately reallocated. If the source of the copy is the
same texture, this causes a crash.
This can be properly supported by using a temp image to do the copy, but
that is not implemented in this change.
Bug: chromium:1501798
Change-Id: I3a902b1e9eec41afd385d9c75a8c95dc986070a8
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5143829
Reviewed-by: Cody Northrop <cnorthrop@google.com>
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532069
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../libANGLE/renderer/vulkan/TextureVk.cpp | 23 ++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 1950375b9b19..a098da4bfd33 100644
--- src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ src/3rdparty/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -466,8 +466,28 @@ angle::Result TextureVk::copyImage(const gl::Context *context,
gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
const vk::Format &vkFormat = renderer->getFormat(internalFormatInfo.sizedInternalFormat);
+ // The texture level being redefined might be the same as the one bound to the framebuffer.
+ // This _could_ be supported by using a temp image before redefining the level (and potentially
+ // discarding the image). However, this is currently unimplemented.
+ FramebufferVk *framebufferVk = vk::GetImpl(source);
+ RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
+ vk::ImageHelper *srcImage = &colorReadRT->getImageForCopy();
+ const bool isCubeMap = index.getType() == gl::TextureType::CubeMap;
+ gl::LevelIndex levelIndex(getNativeImageIndex(index).getLevelIndex());
+ const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
+ const uint32_t redefinedFace = isCubeMap ? layerIndex : 0;
+ const uint32_t sourceFace = isCubeMap ? colorReadRT->getLayerIndex() : 0;
+ const bool isSelfCopy = mImage == srcImage && levelIndex == colorReadRT->getLevelIndex() &&
+ redefinedFace == sourceFace;
+
ANGLE_TRY(redefineLevel(context, index, vkFormat, newImageSize));
+ if (isSelfCopy)
+ {
+ UNIMPLEMENTED();
+ return angle::Result::Continue;
+ }
+
return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo,
source);
}
@@ -1393,7 +1413,8 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context,
mImage->getLevelCount() == 1 && mImage->getBaseLevel() == levelIndexGL;
// If incompatible, and redefining the single-level image, release it so it can be
- // recreated immediately. This is an optimization to avoid an extra copy.
+ // recreated immediately. This is needed so that the texture can be reallocated with
+ // the correct format/size.
if (!isCompatibleRedefinition && isUpdateToSingleLevelImage)
{
releaseImage(contextVk);
From b3bd93f5093ceef2bcf0c2346a2b761455ab842a Mon Sep 17 00:00:00 2001
From: Joshua Pawlicki <waffles@chromium.org>
Date: Wed, 20 Dec 2023 22:33:06 +0000
Subject: [PATCH] [Backport] CVE-2024-0333: Insufficient data validation in
Extensions
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5141787:
crx_file: Error early for CRXs with ZIP markers in header.
Bug: 1513379
Change-Id: I029b4f15778df0c150866b1f49a9b5b2924690ed
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5141787
Commit-Queue: Joshua Pawlicki <waffles@chromium.org>
Auto-Submit: Joshua Pawlicki <waffles@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Commit-Queue: Sorin Jianu <sorin@chromium.org>
Reviewed-by: Sorin Jianu <sorin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1239849}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532070
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
chromium/components/crx_file/crx_verifier.cc | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/chromium/components/crx_file/crx_verifier.cc b/chromium/components/crx_file/crx_verifier.cc
index cbd7d777b6a6..d03cadb150db 100644
--- src/3rdparty/chromium/components/crx_file/crx_verifier.cc
+++ src/3rdparty/chromium/components/crx_file/crx_verifier.cc
@@ -4,6 +4,7 @@
#include "components/crx_file/crx_verifier.h"
+#include <algorithm>
#include <cstring>
#include <iterator>
#include <memory>
@@ -44,6 +45,9 @@ constexpr uint8_t kPublisherTestKeyHash[] = {
0x5f, 0x64, 0xf3, 0xa6, 0x17, 0x03, 0x0d, 0xde, 0x21, 0x61, 0xbe,
0xb7, 0x95, 0x91, 0x95, 0x83, 0x68, 0x12, 0xe9, 0x78, 0x1e};
+constexpr uint8_t kEocd[] = {'P', 'K', 0x05, 0x06};
+constexpr uint8_t kEocd64[] = {'P', 'K', 0x06, 0x07};
+
using VerifierCollection =
std::vector<std::unique_ptr<crypto::SignatureVerifier>>;
using RepeatedProof = google::protobuf::RepeatedPtrField<AsymmetricKeyProof>;
@@ -109,6 +113,18 @@ VerifierResult VerifyCrx3(
if (ReadAndHashBuffer(header_bytes.data(), header_size, file, hash) !=
static_cast<int>(header_size))
return VerifierResult::ERROR_HEADER_INVALID;
+
+ // If the header contains a ZIP EOCD or EOCD64 token, unzipping may not work
+ // correctly.
+ if (std::search(std::begin(header_bytes), std::end(header_bytes),
+ std::begin(kEocd),
+ std::end(kEocd)) != std::end(header_bytes) ||
+ std::search(std::begin(header_bytes), std::end(header_bytes),
+ std::begin(kEocd64),
+ std::end(kEocd64)) != std::end(header_bytes)) {
+ return VerifierResult::ERROR_HEADER_INVALID;
+ }
+
CrxFileHeader header;
if (!header.ParseFromArray(header_bytes.data(), header_size))
return VerifierResult::ERROR_HEADER_INVALID;
From 520c290ba211017b31324cc9f361c0388433616a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20Inf=C3=BChr?= <dinfuehr@chromium.org>
Date: Mon, 18 Dec 2023 09:15:00 +0100
Subject: [PATCH] [Backport] CVE-2024-0518: Type Confusion in V8
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/v8/v8/+/5125960:
[codegen] Install BytecodeArray last in SharedFunctionInfo
Maglev assumes that when a SharedFunctionInfo has a BytecodeArray,
then it should also have FeedbackMetadata. However, this may not
hold with concurrent compilation when the SharedFunctionInfo is
re-compiled after being flushed. Here the BytecodeArray was installed
on the SFI before the FeedbackMetadata and a concurrent thread could
observe the BytecodeArray but not the FeedbackMetadata.
Drive-by: Reset the age field before setting the BytecodeArray as
well. This ensures that the concurrent marker will not observe the
old age for the new BytecodeArray.
Bug: chromium:1507412
Change-Id: I8855ed7ecc50c4a47d2c89043d62ac053858bc75
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5125960
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#91568}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532071
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
---
chromium/v8/src/codegen/compiler.cc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/chromium/v8/src/codegen/compiler.cc b/chromium/v8/src/codegen/compiler.cc
index f09658ebdf62..f963b0d92684 100644
--- src/3rdparty/chromium/v8/src/codegen/compiler.cc
+++ src/3rdparty/chromium/v8/src/codegen/compiler.cc
@@ -543,11 +543,11 @@ void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
shared_info->set_is_asm_wasm_broken(true);
}
- shared_info->set_bytecode_array(*compilation_info->bytecode_array());
-
Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
isolate, compilation_info->feedback_vector_spec());
shared_info->set_feedback_metadata(*feedback_metadata);
+
+ shared_info->set_bytecode_array(*compilation_info->bytecode_array());
} else {
DCHECK(compilation_info->has_asm_wasm_data());
// We should only have asm/wasm data when finalizing on the main thread.
From 6fb8d851a5048e85877ae33b1800c122c8cd034d Mon Sep 17 00:00:00 2001
From: Toon Verwaest <verwaest@chromium.org>
Date: Thu, 11 Jan 2024 10:47:17 +0100
Subject: [PATCH] [Backport] CVE-2024-0519: Out of bounds memory access in V8
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/v8/v8/+/5192447:
Merged: [runtime] Drop fast last-property deletion
This interacts badly with other optimizations and isn't particularly
common.
Bug: chromium:1517354
(cherry picked from commit 389ea9be7d68bb189e16da79f6414edbd4f7594f)
Change-Id: Ie16aa38e8984c4879491c0d9a0ca9df0e041fd1d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5192447
Auto-Submit: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/branch-heads/12.0@{#32}
Cr-Branched-From: ed7b4caf1fb8184ad9e24346c84424055d4d430a-refs/heads/12.0.267@{#1}
Cr-Branched-From: 210e75b19db4352c9b78dce0bae11c2dc3077df4-refs/heads/main@{#90651}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532072
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
---
chromium/v8/src/runtime/runtime-object.cc | 160 ----------------------
1 file changed, 160 deletions(-)
diff --git a/chromium/v8/src/runtime/runtime-object.cc b/chromium/v8/src/runtime/runtime-object.cc
index bd5d23dce45f..075bc0c665d3 100644
--- src/3rdparty/chromium/v8/src/runtime/runtime-object.cc
+++ src/3rdparty/chromium/v8/src/runtime/runtime-object.cc
@@ -92,170 +92,10 @@ MaybeHandle<Object> Runtime::HasProperty(Isolate* isolate,
: ReadOnlyRoots(isolate).false_value_handle();
}
-namespace {
-
-void GeneralizeAllTransitionsToFieldAsMutable(Isolate* isolate, Handle<Map> map,
- Handle<Name> name) {
- InternalIndex descriptor(map->NumberOfOwnDescriptors());
-
- Handle<Map> target_maps[kPropertyAttributesCombinationsCount];
- int target_maps_count = 0;
-
- // Collect all outgoing field transitions.
- {
- DisallowHeapAllocation no_gc;
- TransitionsAccessor transitions(isolate, *map, &no_gc);
- transitions.ForEachTransitionTo(
- *name,
- [&](Map target) {
- DCHECK_EQ(descriptor, target.LastAdded());
- DCHECK_EQ(*name, target.GetLastDescriptorName(isolate));
- PropertyDetails details = target.GetLastDescriptorDetails(isolate);
- // Currently, we track constness only for fields.
- if (details.kind() == kData &&
- details.constness() == PropertyConstness::kConst) {
- target_maps[target_maps_count++] = handle(target, isolate);
- }
- DCHECK_IMPLIES(details.kind() == kAccessor,
- details.constness() == PropertyConstness::kConst);
- },
- &no_gc);
- CHECK_LE(target_maps_count, kPropertyAttributesCombinationsCount);
- }
-
- for (int i = 0; i < target_maps_count; i++) {
- Handle<Map> target = target_maps[i];
- PropertyDetails details =
- target->instance_descriptors(isolate)
- .GetDetails(descriptor);
- Handle<FieldType> field_type(
- target->instance_descriptors(isolate)
- .GetFieldType(descriptor),
- isolate);
- Map::GeneralizeField(isolate, target, descriptor,
- PropertyConstness::kMutable, details.representation(),
- field_type);
- DCHECK_EQ(PropertyConstness::kMutable,
- target->instance_descriptors(isolate)
- .GetDetails(descriptor)
- .constness());
- }
-}
-
-bool DeleteObjectPropertyFast(Isolate* isolate, Handle<JSReceiver> receiver,
- Handle<Object> raw_key) {
- // This implements a special case for fast property deletion: when the
- // last property in an object is deleted, then instead of normalizing
- // the properties, we can undo the last map transition, with a few
- // prerequisites:
- // (1) The receiver must be a regular object and the key a unique name.
- Handle<Map> receiver_map(receiver->map(), isolate);
- if (receiver_map->IsSpecialReceiverMap()) return false;
- DCHECK(receiver_map->IsJSObjectMap());
-
- if (!raw_key->IsUniqueName()) return false;
- Handle<Name> key = Handle<Name>::cast(raw_key);
- // (2) The property to be deleted must be the last property.
- int nof = receiver_map->NumberOfOwnDescriptors();
- if (nof == 0) return false;
- InternalIndex descriptor(nof - 1);
- Handle<DescriptorArray> descriptors(receiver_map->instance_descriptors(),
- isolate);
- if (descriptors->GetKey(descriptor) != *key) return false;
- // (3) The property to be deleted must be deletable.
- PropertyDetails details = descriptors->GetDetails(descriptor);
- if (!details.IsConfigurable()) return false;
- // (4) The map must have a back pointer.
- Handle<Object> backpointer(receiver_map->GetBackPointer(), isolate);
- if (!backpointer->IsMap()) return false;
- Handle<Map> parent_map = Handle<Map>::cast(backpointer);
- // (5) The last transition must have been caused by adding a property
- // (and not any kind of special transition).
- if (parent_map->NumberOfOwnDescriptors() != nof - 1) return false;
-
- // Preconditions successful. No more bailouts after this point.
-
- // Zap the property to avoid keeping objects alive. Zapping is not necessary
- // for properties stored in the descriptor array.
- if (details.location() == kField) {
- DisallowHeapAllocation no_allocation;
-
- // Invalidate slots manually later in case we delete an in-object tagged
- // property. In this case we might later store an untagged value in the
- // recorded slot.
- isolate->heap()->NotifyObjectLayoutChange(*receiver, no_allocation,
- InvalidateRecordedSlots::kNo);
- FieldIndex index =
- FieldIndex::ForPropertyIndex(*receiver_map, details.field_index());
- // Special case deleting the last out-of object property.
- if (!index.is_inobject() && index.outobject_array_index() == 0) {
- DCHECK(!parent_map->HasOutOfObjectProperties());
- // Clear out the properties backing store.
- receiver->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
- } else {
- Object filler = ReadOnlyRoots(isolate).one_pointer_filler_map();
- JSObject::cast(*receiver).RawFastPropertyAtPut(index, filler);
- // We must clear any recorded slot for the deleted property, because
- // subsequent object modifications might put a raw double there.
- // Slot clearing is the reason why this entire function cannot currently
- // be implemented in the DeleteProperty stub.
- if (index.is_inobject() && !receiver_map->IsUnboxedDoubleField(index)) {
- // We need to clear the recorded slot in this case because in-object
- // slack tracking might not be finished. This ensures that we don't
- // have recorded slots in free space.
- isolate->heap()->ClearRecordedSlot(*receiver,
- receiver->RawField(index.offset()));
- MemoryChunk* chunk = MemoryChunk::FromHeapObject(*receiver);
- chunk->InvalidateRecordedSlots(*receiver);
- }
- }
- }
- // If the {receiver_map} was marked stable before, then there could be
- // optimized code that depends on the assumption that no object that
- // reached this {receiver_map} transitions away from it without triggering
- // the "deoptimize dependent code" mechanism.
- receiver_map->NotifyLeafMapLayoutChange(isolate);
- // Finally, perform the map rollback.
- receiver->synchronized_set_map(*parent_map);
-#if VERIFY_HEAP
- receiver->HeapObjectVerify(isolate);
- receiver->property_array().PropertyArrayVerify(isolate);
-#endif
-
- // If the {descriptor} was "const" so far, we need to update the
- // {receiver_map} here, otherwise we could get the constants wrong, i.e.
- //
- // o.x = 1;
- // [change o.x's attributes or reconfigure property kind]
- // delete o.x;
- // o.x = 2;
- //
- // could trick V8 into thinking that `o.x` is still 1 even after the second
- // assignment.
-
- // Step 1: Migrate object to an up-to-date shape.
- if (parent_map->is_deprecated()) {
- JSObject::MigrateInstance(isolate, Handle<JSObject>::cast(receiver));
- parent_map = handle(receiver->map(), isolate);
- }
-
- // Step 2: Mark outgoing transitions from the up-to-date version of the
- // parent_map to same property name of any kind or attributes as mutable.
- // Also migrate object to the up-to-date map to make the object shapes
- // converge sooner.
- GeneralizeAllTransitionsToFieldAsMutable(isolate, parent_map, key);
-
- return true;
-}
-
-} // namespace
-
Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate,
Handle<JSReceiver> receiver,
Handle<Object> key,
LanguageMode language_mode) {
- if (DeleteObjectPropertyFast(isolate, receiver, key)) return Just(true);
-
bool success = false;
LookupIterator::Key lookup_key(isolate, key, &success);
if (!success) return Nothing<bool>();
From 1dbdcfd64885f0dc034e73dacf6ef4e20f8351bf Mon Sep 17 00:00:00 2001
From: Mike Wasserman <msw@chromium.org>
Date: Tue, 9 Jan 2024 01:07:39 +0000
Subject: [PATCH] [Backport] Security bug 1506535
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5146875:
[M120 merge] Speculative fix for UAF in content::WebContentsImpl::ExitFullscreenMode
(cherry picked from commit c1cda70a433a0c625b280eb88ed6ff4f4feffa12)
Bug: 1506535, 854815
Change-Id: Iace64d63f8cea2dbfbc761ad233db42451ec101c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5146875
Commit-Queue: John Abd-El-Malek <jam@chromium.org>
Auto-Submit: Mike Wasserman <msw@chromium.org>
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1240353}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5178801
Cr-Commit-Position: refs/branch-heads/6099@{#1727}
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532073
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
chromium/content/browser/web_contents/web_contents_impl.cc | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 0627170ed036..23d4268a1b67 100644
--- src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.cc
+++ src/3rdparty/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -3278,7 +3278,12 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
}
if (delegate_) {
+ // This may spin the message loop and destroy this object crbug.com/1506535
+ base::WeakPtr<WebContentsImpl> weak_ptr = weak_factory_.GetWeakPtr();
delegate_->ExitFullscreenModeForTab(this);
+ if (!weak_ptr) {
+ return;
+ }
if (keyboard_lock_widget_)
delegate_->CancelKeyboardLockRequest(this);
From 1c6050c84b2a8bd14a96787ca845a3aec0d87a4f Mon Sep 17 00:00:00 2001
From: Gustaf Ullberg <gustaf@chromium.org>
Date: Tue, 19 Dec 2023 18:08:19 +0000
Subject: [PATCH] [Backport] CVE-2023-7024: Heap buffer overflow in WebRTC
Cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5136295:
WebRtcAudioSink: Stop on invalid configuration
Bug: 1513170
Change-Id: Ia4ca55e9eafb81789b28b8b8c54e615ac28df633
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5136295
Reviewed-by: Harald Alvestrand <hta@chromium.org>
Commit-Queue: Gustaf Ullberg <gustaf@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1239233}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532066
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../blink/renderer/platform/peerconnection/webrtc_audio_sink.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc b/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc
index a0f2c5e8005f..0542a9a7d4c0 100644
--- src/3rdparty/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/platform/peerconnection/webrtc_audio_sink.cc
@@ -115,7 +115,7 @@ void WebRtcAudioSink::OnData(const media::AudioBus& audio_bus,
}
void WebRtcAudioSink::OnSetFormat(const media::AudioParameters& params) {
- DCHECK(params.IsValid());
+ CHECK(params.IsValid());
SendLogMessage(base::StringPrintf("OnSetFormat([label=%s] {params=[%s]})",
adapter_->label().c_str(),
params.AsHumanReadableString().c_str()));
From 525ae23fbd019ab819a2f7e26e43bfce4ee79c51 Mon Sep 17 00:00:00 2001
From: Hongchan Choi <hongchan@chromium.org>
Date: Tue, 12 Dec 2023 02:36:08 +0000
Subject: [PATCH] [Backport] CVE-2024-0224: Use after free in WebAudio
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5112992:
Wrap buffer read index in delay kernel
The current code assumes that the first buffer read index in the delay
kernel does not go out of bound. This CL applies the wrapping function
to the read index array.
(cherry picked from commit fb96fd5f41bec823dbb208d9a7d53fbbf4d16ce4)
Bug: 1505086
Test: Locally confirmed the repro does not crash anymore
Change-Id: Idca3dfc7dec5b5a7f9b22d87135e2d775729631a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5072113
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Reviewed-by: Michael Wilson <mjwilson@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1231040}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5112992
Auto-Submit: Hongchan Choi <hongchan@chromium.org>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/6099@{#1498}
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532067
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../renderer/platform/audio/audio_delay_dsp_kernel.cc | 2 +-
.../audio/cpu/arm/audio_delay_dsp_kernel_neon.cc | 7 +++++--
.../audio/cpu/x86/audio_delay_dsp_kernel_sse2.cc | 10 +++++++---
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc b/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
index 25818dcf2aa7..c34118e953ac 100644
--- src/3rdparty/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
@@ -150,7 +150,7 @@ int AudioDelayDSPKernel::ProcessARateScalar(unsigned start,
const float* delay_times = delay_times_.Data();
for (unsigned i = start; i < frames_to_process; ++i) {
- double delay_time = delay_times[i];
+ double delay_time = std::fmax(delay_times[i], 0);
double desired_delay_frames = delay_time * sample_rate;
double read_position = w_index + buffer_length - desired_delay_frames;
diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/arm/audio_delay_dsp_kernel_neon.cc b/chromium/third_party/blink/renderer/platform/audio/cpu/arm/audio_delay_dsp_kernel_neon.cc
index 2843bd60b8ba..803f3e724423 100644
--- src/3rdparty/chromium/third_party/blink/renderer/platform/audio/cpu/arm/audio_delay_dsp_kernel_neon.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/platform/audio/cpu/arm/audio_delay_dsp_kernel_neon.cc
@@ -60,6 +60,7 @@ std::tuple<unsigned, int> AudioDelayDSPKernel::ProcessARateVector(
int w_index = write_index_;
const float32x4_t v_sample_rate = vdupq_n_f32(sample_rate);
+ const float32x4_t v_all_zeros = vdupq_n_f32(0);
// The buffer length as a float and as an int so we don't need to constant
// convert from one to the other.
@@ -87,7 +88,8 @@ std::tuple<unsigned, int> AudioDelayDSPKernel::ProcessARateVector(
int k = 0;
for (int n = 0; n < number_of_loops; ++n, k += 4) {
- const float32x4_t v_delay_time = vld1q_f32(delay_times + k);
+ const float32x4_t v_delay_time = vmaxq_f32(vld1q_f32(delay_times + k),
+ v_all_zeros);
const float32x4_t v_desired_delay_frames =
vmulq_f32(v_delay_time, v_sample_rate);
@@ -100,7 +102,8 @@ std::tuple<unsigned, int> AudioDelayDSPKernel::ProcessARateVector(
WrapPositionVector(v_read_position, v_buffer_length_float);
// Get indices into the buffer for the samples we need for interpolation.
- const int32x4_t v_read_index1 = vcvtq_s32_f32(v_read_position);
+ const int32x4_t v_read_index1 = WrapIndexVector(
+ vcvtq_s32_f32(v_read_position), v_buffer_length_int);
const int32x4_t v_read_index2 = WrapIndexVector(
vaddq_s32(v_read_index1, vdupq_n_s32(1)), v_buffer_length_int);
diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/audio_delay_dsp_kernel_sse2.cc b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/audio_delay_dsp_kernel_sse2.cc
index fe2aef95aeda..dd368ee4b0f4 100644
--- src/3rdparty/chromium/third_party/blink/renderer/platform/audio/cpu/x86/audio_delay_dsp_kernel_sse2.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/platform/audio/cpu/x86/audio_delay_dsp_kernel_sse2.cc
@@ -56,10 +56,10 @@ std::tuple<unsigned, int> AudioDelayDSPKernel::ProcessARateVector(
const float sample_rate = this->SampleRate();
const float* delay_times = delay_times_.Data();
-
int w_index = write_index_;
const __m128 v_sample_rate = _mm_set1_ps(sample_rate);
+ const __m128 v_all_zeros = _mm_setzero_ps();
// The buffer length as a float and as an int so we don't need to constant
// convert from one to the other.
@@ -82,7 +82,10 @@ std::tuple<unsigned, int> AudioDelayDSPKernel::ProcessARateVector(
int k = 0;
for (int n = 0; n < number_of_loops; ++n, k += 4) {
- const __m128 v_delay_time = _mm_loadu_ps(delay_times + k);
+ // It's possible that `delay_time` contains negative values. Make sure
+ // they are greater than zero.
+ const __m128 v_delay_time = _mm_max_ps(_mm_loadu_ps(delay_times + k),
+ v_all_zeros);
const __m128 v_desired_delay_frames =
_mm_mul_ps(v_delay_time, v_sample_rate);
@@ -95,7 +98,8 @@ std::tuple<unsigned, int> AudioDelayDSPKernel::ProcessARateVector(
WrapPositionVector(v_read_position, v_buffer_length_float);
// Get indices into the buffer for the samples we need for interpolation.
- const __m128i v_read_index1 = _mm_cvttps_epi32(v_read_position);
+ const __m128i v_read_index1 = WrapIndexVector(
+ _mm_cvttps_epi32(v_read_position), v_buffer_length_int);
const __m128i v_read_index2 = WrapIndexVector(
_mm_add_epi32(v_read_index1, _mm_set1_epi32(1)), v_buffer_length_int);
From c96132ccf271137bbd3f5b1a8c9c172650e69526 Mon Sep 17 00:00:00 2001
From: Evan Stade <estade@chromium.org>
Date: Fri, 15 Dec 2023 21:38:02 +0000
Subject: [PATCH] [Backport] Security bug 1511689
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/deps/sqlite/+/5123910:
Fix a spurious "misuse of aggregate function" error that could occur when an aggregate function was used within the FROM clause of a sub-select of the select that owns the aggregate. e.g. "SELECT (SELECT x FROM (SELECT sum(t1.a) AS x)) FROM t1". [forum:/forumpost/c9970a37ed | Forum post c9970a37ed].
FossilOrigin-Name: 4470f657d2069972d02a00983252dec1f814d90c0d8d0906e320e955111e8c11
(cherry picked from commit 5e4233a9e48b124d4d342b757b34e4ae849f5cf8)
Bug: 1511689
Change-Id: I69263fc0a5fa66df5c09b964864568f2fc7a6ca5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/deps/sqlite/+/5123910
Auto-Submit: Evan Stade <estade@chromium.org>
Commit-Queue: Ayu Ishii <ayui@chromium.org>
Reviewed-by: Ayu Ishii <ayui@chromium.org>
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532068
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
chromium/third_party/sqlite/src/amalgamation/sqlite3.c | 6 +++++-
chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c | 6 +++++-
chromium/third_party/sqlite/src/src/resolve.c | 7 +++++--
chromium/third_party/sqlite/src/src/sqliteInt.h | 1 +
4 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/chromium/third_party/sqlite/src/amalgamation/sqlite3.c b/chromium/third_party/sqlite/src/amalgamation/sqlite3.c
index d7766b7d7ec..b353aa88348 100644
--- src/3rdparty/chromium/third_party/sqlite/src/amalgamation/sqlite3.c
+++ src/3rdparty/chromium/third_party/sqlite/src/amalgamation/sqlite3.c
@@ -18804,6 +18804,7 @@ struct NameContext {
int nRef; /* Number of names resolved by this context */
int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
+ int nNestedSelect; /* Number of nested selects using this NC */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -104749,11 +104750,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
while( pNC2
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
){
- pExpr->op2++;
+ pExpr->op2 += (1 + pNC2->nNestedSelect);
pNC2 = pNC2->pNext;
}
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
+ pExpr->op2 += pNC2->nNestedSelect;
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
@@ -105314,6 +105316,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Recursively resolve names in all subqueries in the FROM clause
*/
+ if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
@@ -105338,6 +105341,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
}
+ if( pOuterNC ) pOuterNC->nNestedSelect--;
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
diff --git a/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c b/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c
index 0819ea6a615..5c72a44dd6b 100644
--- src/3rdparty/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c
+++ src/3rdparty/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c
@@ -18817,6 +18817,7 @@ struct NameContext {
int nRef; /* Number of names resolved by this context */
int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
+ int nNestedSelect; /* Number of nested selects using this NC */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -104762,11 +104763,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
while( pNC2
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
){
- pExpr->op2++;
+ pExpr->op2 += (1 + pNC2->nNestedSelect);
pNC2 = pNC2->pNext;
}
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
+ pExpr->op2 += pNC2->nNestedSelect;
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
@@ -105327,6 +105329,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Recursively resolve names in all subqueries in the FROM clause
*/
+ if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
@@ -105351,6 +105354,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
}
+ if( pOuterNC ) pOuterNC->nNestedSelect--;
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
diff --git a/chromium/third_party/sqlite/src/src/resolve.c b/chromium/third_party/sqlite/src/src/resolve.c
index 4b36ecca348..c5228a7f097 100644
--- src/3rdparty/chromium/third_party/sqlite/src/src/resolve.c
+++ src/3rdparty/chromium/third_party/sqlite/src/src/resolve.c
@@ -1211,11 +1211,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
while( pNC2
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
){
- pExpr->op2++;
+ pExpr->op2 += (1 + pNC2->nNestedSelect);
pNC2 = pNC2->pNext;
}
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
+ pExpr->op2 += pNC2->nNestedSelect;
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
@@ -1776,6 +1777,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Recursively resolve names in all subqueries in the FROM clause
*/
+ if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
@@ -1800,7 +1802,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
}
-
+ if( pOuterNC ) pOuterNC->nNestedSelect--;
+
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
*/
diff --git a/chromium/third_party/sqlite/src/src/sqliteInt.h b/chromium/third_party/sqlite/src/src/sqliteInt.h
index 2614f4be458..07bc4def106 100644
--- src/3rdparty/chromium/third_party/sqlite/src/src/sqliteInt.h
+++ src/3rdparty/chromium/third_party/sqlite/src/src/sqliteInt.h
@@ -3321,6 +3321,7 @@ struct NameContext {
int nRef; /* Number of names resolved by this context */
int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
+ int nNestedSelect; /* Number of nested selects using this NC */
Select *pWinSelect; /* SELECT statement for any window functions */
};
From f1ef87d506845dd62bb0802e80092d53100222f4 Mon Sep 17 00:00:00 2001
From: Hongchan Choi <hongchan@chromium.org>
Date: Fri, 12 Jan 2024 22:57:22 +0000
Subject: [PATCH] [Backport] CVE-2024-0807: Use after free in WebAudio
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5225523:
Update rendering state of automatic pull nodes before graph rendering
M114 merge issues:
third_party/blink/renderer/modules/webaudio/analyser_handler.cc:
PullInputs/CheckNumberOfChannelsForInput not present in 114.
In rare cases, the rendering fan out count of automatic pull node
does not match the main thread fan out count after recreating
a platform destination followed by disconnection.
This CL forces the update of the rendering state of automatic
pull nodes before graph rendering to make sure that fan out counts
are synchronized before executing the audio processing function call.
NOTE: This change makes 2 WPTs fail. The follow-up work is planned
to address them once this patch is merged.
Bug: 1505080
Test: Locally confirmed that ASAN doesn't crash on all repro cases.
Change-Id: I6768cd8bc64525ea9d56a19b9c58439e9cdab9a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5131958
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1246718}
(cherry picked from commit f4bffa09b46c21147431179e1e6dd2b27bc35fbc)
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/537374
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../renderer/modules/webaudio/analyser_node.cc | 11 +++++++++--
.../renderer/modules/webaudio/audio_worklet_node.cc | 13 +++++++++----
.../modules/webaudio/audio_worklet_processor.cc | 6 ++++++
.../modules/webaudio/deferred_task_handler.cc | 10 ++++++++++
4 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
index cb281f5b728f..9f515af5d9a9 100644
--- src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
@@ -51,9 +51,11 @@ AnalyserHandler::~AnalyserHandler() {
}
void AnalyserHandler::Process(uint32_t frames_to_process) {
- AudioBus* output_bus = Output(0).Bus();
+ DCHECK(Context()->IsAudioThread());
- if (!IsInitialized()) {
+ AudioBus* output_bus = Output(0).RenderingFanOutCount() > 0 ? Output(0).Bus() : nullptr;
+
+ if (!IsInitialized() && output_bus) {
output_bus->Zero();
return;
}
@@ -65,6 +67,11 @@ void AnalyserHandler::Process(uint32_t frames_to_process) {
// Analyser reflects the current input.
analyser_.WriteInput(input_bus.get(), frames_to_process);
+ // Subsequent steps require `output_bus` to be valid.
+ if (!output_bus) {
+ return;
+ }
+
if (!Input(0).IsConnected()) {
// No inputs, so clear the output, and propagate the silence hint.
output_bus->Zero();
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
index eccf002b6da6..5f18c4cd12d2 100644
--- src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
@@ -102,11 +102,16 @@ void AudioWorkletHandler::Process(uint32_t frames_to_process) {
// We also need to check if the global scope is valid before we request
// the rendering in the AudioWorkletGlobalScope.
if (processor_ && !processor_->hasErrorOccurred()) {
- // If the input is not connected, inform the processor with nullptr.
- for (unsigned i = 0; i < NumberOfInputs(); ++i)
+ // If the input or the output is not connected, inform the processor with
+ // nullptr.
+ for (unsigned i = 0; i < NumberOfInputs(); ++i) {
inputs_[i] = Input(i).IsConnected() ? Input(i).Bus() : nullptr;
- for (unsigned i = 0; i < NumberOfOutputs(); ++i)
- outputs_[i] = WrapRefCounted(Output(i).Bus());
+ }
+ for (unsigned i = 0; i < NumberOfOutputs(); ++i) {
+ outputs_[i] = Output(i).RenderingFanOutCount() > 0
+ ? WrapRefCounted(Output(i).Bus())
+ : nullptr;
+ }
for (const auto& param_name : param_value_map_.Keys()) {
auto* const param_handler = param_handler_map_.at(param_name);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
index e68b1c1b2f6b..84ab72b9774c 100644
--- src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
@@ -343,6 +343,12 @@ void AudioWorkletProcessor::CopyArrayBuffersToPort(
for (uint32_t bus_index = 0; bus_index < audio_port.size(); ++bus_index) {
const scoped_refptr<AudioBus>& audio_bus = audio_port[bus_index];
+
+ // nullptr indicates the output bus is not connected. Do not proceed.
+ if (!audio_bus) {
+ break;
+ }
+
for (uint32_t channel_index = 0;
channel_index < audio_bus->NumberOfChannels(); ++channel_index) {
const v8::ArrayBuffer::Contents& contents =
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc b/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
index 76aa9acccd30..88e4228caefa 100644
--- src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
@@ -169,6 +169,16 @@ void DeferredTaskHandler::UpdateAutomaticPullNodes() {
if (try_locker.Locked()) {
CopyToVector(automatic_pull_handlers_,
rendering_automatic_pull_handlers_);
+
+ // In rare cases, it is possible for automatic pull nodes' output bus
+ // to become stale. Make sure update their rendering output counts.
+ // crbug.com/1505080.
+ for (auto& handler : rendering_automatic_pull_handlers_) {
+ for (unsigned i = 0; i < handler->NumberOfOutputs(); ++i) {
+ handler->Output(i).UpdateRenderingState();
+ }
+ }
+
automatic_pull_handlers_need_updating_ = false;
}
}
From 850527b41e56a8b48d99513eddcc75d4efe3c16d Mon Sep 17 00:00:00 2001
From: Lyra Rebane <rebane2001@gmail.com>
Date: Mon, 8 Jan 2024 13:39:46 +0000
Subject: [PATCH] [Backport] CVE-2024-0808: Integer underflow in WebUI
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5177426:
[M114-LTS] Verify resource order in data pack files
This CL adds a resource order check when loading a data pack or calling DataPack::GetStringPiece to make sure the resources are ordered sequentially in memory.
Bug: 1504936
Change-Id: Ie3bf1d9dbac937407355935a859a5daa9ce84350
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5059113
Commit-Queue: Peter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1238675}
(cherry picked from commit c4b2e6246ad0e95eaf0727bb25a2e4969155e989)
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/537375
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
chromium/AUTHORS | 1 +
chromium/ui/base/resource/data_pack.cc | 19 ++++++++++++++++++-
.../ui/base/resource/data_pack_literal.cc | 12 ++++++++++++
chromium/ui/base/resource/data_pack_literal.h | 2 ++
4 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/chromium/AUTHORS b/chromium/AUTHORS
index 92f53ac669a0..9d61a61e57b9 100644
--- src/3rdparty/chromium/AUTHORS
+++ src/3rdparty/chromium/AUTHORS
@@ -631,6 +631,7 @@ Luke Inman-Semerau <luke.semerau@gmail.com>
Luke Seunghoe Gu <gulukesh@gmail.com>
Luke Zarko <lukezarko@gmail.com>
Luoxi Pan <l.panpax@gmail.com>
+Lyra Rebane <rebane2001@gmail.com>
Maarten Lankhorst <m.b.lankhorst@gmail.com>
Magnus Danielsson <fuzzac@gmail.com>
Mahesh Kulkarni <mahesh.kk@samsung.com>
diff --git a/chromium/ui/base/resource/data_pack.cc b/chromium/ui/base/resource/data_pack.cc
index 09513e6aed24..4e522c9ad758 100644
--- src/3rdparty/chromium/ui/base/resource/data_pack.cc
+++ src/3rdparty/chromium/ui/base/resource/data_pack.cc
@@ -400,7 +400,16 @@ bool DataPack::LoadImpl(std::unique_ptr<DataPack::DataSource> data_source) {
}
}
- // 3) Verify the aliases are within the appropriate bounds.
+ // 3) Verify the entries are ordered correctly.
+ for (size_t i = 0; i < resource_count_; ++i) {
+ if (resource_table_[i].file_offset > resource_table_[i + 1].file_offset) {
+ LOG(ERROR) << "Data pack file corruption: "
+ << "Entry #" << i + 1 << " before Entry #" << i << ".";
+ return false;
+ }
+ }
+
+ // 4) Verify the aliases are within the appropriate bounds.
for (size_t i = 0; i < alias_count_; ++i) {
if (alias_table_[i].entry_index >= resource_count_) {
LOG(ERROR) << "Data pack file corruption: "
@@ -461,6 +470,14 @@ bool DataPack::GetStringPiece(uint16_t resource_id,
<< "file modified?";
return false;
}
+ if (target->file_offset > next_entry->file_offset) {
+ size_t entry_index = target - resource_table_;
+ size_t next_index = next_entry - resource_table_;
+ LOG(ERROR) << "Entry #" << next_index << " in data pack is before Entry #"
+ << entry_index << ". This should have been caught when loading. "
+ << "Was the file modified?";
+ return false;
+ }
MaybePrintResourceId(resource_id);
size_t length = next_entry->file_offset - target->file_offset;
diff --git a/chromium/ui/base/resource/data_pack_literal.cc b/chromium/ui/base/resource/data_pack_literal.cc
index f6669ed82447..70e225b6e84e 100644
--- src/3rdparty/chromium/ui/base/resource/data_pack_literal.cc
+++ src/3rdparty/chromium/ui/base/resource/data_pack_literal.cc
@@ -91,6 +91,18 @@ const char kSampleCorruptPakContents[] = {
const size_t kSampleCorruptPakSize = sizeof(kSampleCorruptPakContents);
+const uint8_t kSampleMisorderedPakContents[] = {
+ 0x05, 0x00, 0x00, 0x00, // version
+ 0x01, 0x00, 0x00, 0x00, // encoding + padding
+ 0x02, 0x00, 0x00, 0x00, // num_resources, num_aliases
+ 0x06, 0x00, 0x2a, 0x00, 0x00, 0x00, // index entry 6 (wrong order)
+ 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, // index entry 4
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, // extra entry for the size of last
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '4',
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '6'};
+
+const size_t kSampleMisorderedPakSize = sizeof(kSampleMisorderedPakContents);
+
const char kSamplePakContents2x[] = {
0x04, 0x00, 0x00, 0x00, // header(version
0x01, 0x00, 0x00, 0x00, // no. entries
diff --git a/chromium/ui/base/resource/data_pack_literal.h b/chromium/ui/base/resource/data_pack_literal.h
index 83a8dc04c141..a7fcf2bf85c7 100644
--- src/3rdparty/chromium/ui/base/resource/data_pack_literal.h
+++ src/3rdparty/chromium/ui/base/resource/data_pack_literal.h
@@ -19,6 +19,8 @@ extern const char kEmptyPakContents[];
extern const size_t kEmptyPakSize;
extern const char kSampleCorruptPakContents[];
extern const size_t kSampleCorruptPakSize;
+extern const uint8_t kSampleMisorderedPakContents[];
+extern const size_t kSampleMisorderedPakSize;
} // namespace ui
From 629a490cede4673cec29addd4629c432319a3b6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20Bostr=C3=B6m?= <pbos@chromium.org>
Date: Tue, 23 Jan 2024 01:06:06 +0000
Subject: [PATCH] [Backport] Security bug 1519980
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5226127:
Speculatively fix race in mojo ShutDownOnIOThread
This acquires `write_lock_` before resetting handles used by WriteNoLock
(which is called under the same lock in another thread). We also set
`reject_writes_` to prevent future write attempts after shutdown. That
seems strictly more correct.
We also acquire `fds_to_close_lock_` before clearing the FDs.
I was unable to repro locally as content_browsertests just times out
in my local setup without reporting anything interesting. This seems
strictly more correct though.
Bug: 1519980
Change-Id: I96279936ca908ecb98eddd381df20d61597cba43
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5226127
Auto-Submit: Peter Boström <pbos@chromium.org>
Reviewed-by: Ken Rockot <rockot@google.com>
Commit-Queue: Ken Rockot <rockot@google.com>
Commit-Queue: Peter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1250580}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/537376
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
chromium/mojo/core/channel_posix.cc | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/chromium/mojo/core/channel_posix.cc b/chromium/mojo/core/channel_posix.cc
index d7d9d6cfee15..e17aa8d82a91 100644
--- src/3rdparty/chromium/mojo/core/channel_posix.cc
+++ src/3rdparty/chromium/mojo/core/channel_posix.cc
@@ -242,18 +242,23 @@ class ChannelPosix : public Channel,
void ShutDownOnIOThread() {
base::CurrentThread::Get()->RemoveDestructionObserver(this);
- read_watcher_.reset();
- write_watcher_.reset();
- if (leak_handle_) {
- ignore_result(socket_.release());
- server_.TakePlatformHandle().release();
- } else {
- socket_.reset();
- ignore_result(server_.TakePlatformHandle());
+ {
+ base::AutoLock lock(write_lock_);
+ reject_writes_ = true;
+ read_watcher_.reset();
+ write_watcher_.reset();
+ if (leak_handle_) {
+ std::ignore = socket_.release();
+ server_.TakePlatformHandle().release();
+ } else {
+ socket_.reset();
+ std::ignore = server_.TakePlatformHandle();
+ }
+ #if defined(OS_IOS)
+ base::AutoLock fd_lock(fds_to_close_lock_);
+ fds_to_close_.clear();
+ #endif
}
-#if defined(OS_IOS)
- fds_to_close_.clear();
-#endif
// May destroy the |this| if it was the last reference.
self_ = nullptr;
From 024962f9456bbb5823a877441e92ca3af30279a6 Mon Sep 17 00:00:00 2001
From: Tsuyoshi Horo <horo@chromium.org>
Date: Tue, 9 Jan 2024 08:40:00 +0000
Subject: [PATCH] [Backport] CVE-2024-1077: Use after free in Network
Cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5179746:
Fix UAF in SourceStreamToDataPipe
SourceStreamToDataPipe::ReadMore() is passing a callback with
Unretained(this) to net::SourceStream::Read(). But this callback may be
called even after the SourceStream is destructed. This is causing UAF
issue (crbug.com/1511085).
To solve this problem, this CL changes ReadMore() method to pass a
callback with a weak ptr of this.
Bug: 1511085
Change-Id: Idd4e34ff300ff5db2de1de7b303841c7db3a964a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5179746
Reviewed-by: Adam Rice <ricea@chromium.org>
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1244526}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/537377
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../network/public/cpp/source_stream_to_data_pipe.cc | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/chromium/services/network/public/cpp/source_stream_to_data_pipe.cc b/chromium/services/network/public/cpp/source_stream_to_data_pipe.cc
index d6ade7b0ec52..615804ad8d29 100644
--- src/3rdparty/chromium/services/network/public/cpp/source_stream_to_data_pipe.cc
+++ src/3rdparty/chromium/services/network/public/cpp/source_stream_to_data_pipe.cc
@@ -53,9 +53,9 @@ void SourceStreamToDataPipe::ReadMore() {
scoped_refptr<net::IOBuffer> buffer(
new network::NetToMojoIOBuffer(pending_write_.get()));
- int result = source_->Read(
- buffer.get(), base::checked_cast<int>(num_bytes),
- base::BindOnce(&SourceStreamToDataPipe::DidRead, base::Unretained(this)));
+ int result = source_->Read(buffer.get(), base::checked_cast<int>(num_bytes),
+ base::BindOnce(&SourceStreamToDataPipe::DidRead,
+ weak_factory_.GetWeakPtr()));
if (result != net::ERR_IO_PENDING)
DidRead(result);
From 06e89516b94241e088f6d350bc3a113e726355cd Mon Sep 17 00:00:00 2001
From: Jean-Philippe Gravel <jpgravel@chromium.org>
Date: Wed, 17 Jan 2024 17:45:45 +0000
Subject: [PATCH] [Backport] CVE-2024-1060: Use after free in Canvas
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5198419:
Fix use-after-free in DrawTextInternal
DrawTextInternal was calling GetOrCreatePaintCanvas multiple times,
once at the start of the function, once inside of the
BaseRenderingContext2DAutoRestoreSkCanvas helper class and once in the
Draw call. GetOrCreatePaintCanvas destroys the canvas resource provider
if the GPU context is lost. If this happens on the second call to
GetOrCreatePaintCanvas, destroying the resource provider will
invalidate the cc::PaintCanvas returned by the first call to
GetOrCreatePaintCanvas.
The GPU process can technically crash at any point during the renderer
process execution (perhaps because of something another renderer
process did). We therefore have to assume that any call to
GetOrCreatePaintCanvas can invalidate previously returned
cc::PaintCanvas.
Change-Id: Ifa77735ab1b2b55b3d494f886b8566299937f6fe
Fixed: 1511567
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5198419
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
Commit-Queue: Jean-Philippe Gravel <jpgravel@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1248204}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/537378
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../canvas2d/canvas_rendering_context_2d.cc | 50 ++++++-------------
.../canvas2d/canvas_rendering_context_2d.h | 2 -
2 files changed, 16 insertions(+), 36 deletions(-)
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
index ade14e0102ae..fe8c4cd277ce 100644
--- src/3rdparty/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -86,35 +86,6 @@ static bool ContextLostRestoredEventsEnabled() {
return RuntimeEnabledFeatures::Canvas2dContextLostRestoredEnabled();
}
-// Drawing methods need to use this instead of SkAutoCanvasRestore in case
-// overdraw detection substitutes the recording canvas (to discard overdrawn
-// draw calls).
-class CanvasRenderingContext2DAutoRestoreSkCanvas {
- STACK_ALLOCATED();
-
- public:
- explicit CanvasRenderingContext2DAutoRestoreSkCanvas(
- CanvasRenderingContext2D* context)
- : context_(context), save_count_(0) {
- DCHECK(context_);
- cc::PaintCanvas* c = context_->GetOrCreatePaintCanvas();
- if (c) {
- save_count_ = c->getSaveCount();
- }
- }
-
- ~CanvasRenderingContext2DAutoRestoreSkCanvas() {
- cc::PaintCanvas* c = context_->GetOrCreatePaintCanvas();
- if (c)
- c->restoreToCount(save_count_);
- context_->ValidateStateStack();
- }
-
- private:
- CanvasRenderingContext2D* context_;
- int save_count_;
-};
-
CanvasRenderingContext2D::CanvasRenderingContext2D(
HTMLCanvasElement* canvas,
const CanvasContextCreationAttributesCore& attrs)
@@ -850,9 +821,11 @@ void CanvasRenderingContext2D::DrawTextInternal(
// to 0, for example), so update style before grabbing the PaintCanvas.
canvas()->GetDocument().UpdateStyleAndLayoutTreeForNode(canvas());
- cc::PaintCanvas* c = GetOrCreatePaintCanvas();
- if (!c)
+ // Abort if we don't have a paint canvas (e.g. the context was lost).
+ cc::PaintCanvas* paint_canvas = GetOrCreatePaintCanvas();
+ if (!paint_canvas) {
return;
+ }
if (!std::isfinite(x) || !std::isfinite(y))
return;
@@ -920,14 +893,13 @@ void CanvasRenderingContext2D::DrawTextInternal(
if (paint_type == CanvasRenderingContext2DState::kStrokePaintType)
InflateStrokeRect(bounds);
- CanvasRenderingContext2DAutoRestoreSkCanvas state_restorer(this);
if (use_max_width) {
- c->save();
+ paint_canvas->save();
// We draw when fontWidth is 0 so compositing operations (eg, a "copy" op)
// still work. As the width of canvas is scaled, so text can be scaled to
// match the given maxwidth, update text location so it appears on desired
// place.
- c->scale(clampTo<float>(width / font_width), 1);
+ paint_canvas->scale(clampTo<float>(width / font_width), 1);
location.SetX(location.X() / clampTo<float>(width / font_width));
}
@@ -942,6 +914,16 @@ void CanvasRenderingContext2D::DrawTextInternal(
[](const SkIRect& rect) // overdraw test lambda
{ return false; },
bounds, paint_type, CanvasRenderingContext2DState::kNoImage);
+
+ if (use_max_width) {
+ // Cannot use `paint_canvas` in case recording canvas was substituted or
+ // destroyed during draw call.
+ cc::PaintCanvas* c = GetPaintCanvas();
+ if (c) {
+ c->restore();
+ }
+ }
+ ValidateStateStack();
}
const Font& CanvasRenderingContext2D::AccessFont() {
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
index ac10ae4389a8..b0d09f182a7d 100644
--- src/3rdparty/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
+++ src/3rdparty/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
@@ -236,8 +236,6 @@ class MODULES_EXPORT CanvasRenderingContext2D final
void WillOverwriteCanvas() override;
private:
- friend class CanvasRenderingContext2DAutoRestoreSkCanvas;
-
void DispatchContextLostEvent(TimerBase*);
void DispatchContextRestoredEvent(TimerBase*);
void TryRestoreContextEvent(TimerBase*);
From 6f0832285560ce72dfe1403a1c2d7a53f6bf7f55 Mon Sep 17 00:00:00 2001
From: John Stiles <johnstiles@google.com>
Date: Mon, 29 Jan 2024 23:50:14 +0000
Subject: [PATCH] [Backport] CVE-2024-1283: Heap buffer overflow in Skia
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/5241305:
Fix a crash when a BMP image contains an unnecessary EOF code.
Previously, this would try to perform color correction on a row
one past the end of the image data.
Bug: 1521893
Change-Id: I425437005b9ef400138556705616095857d2cf0d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5241305
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1253633}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/538168
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
---
.../image-decoders/bmp/bmp_image_reader.cc | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
index 562223397030..662e66cab884 100644
--- src/3rdparty/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
+++ src/3rdparty/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
@@ -827,8 +827,11 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessRLEData() {
// the image.
const uint8_t count = ReadUint8(0);
const uint8_t code = ReadUint8(1);
- if ((count || (code != 1)) && PastEndOfImage(0))
+ const bool is_past_end_of_image = PastEndOfImage(0);
+ if ((count || (code != 1)) && is_past_end_of_image) {
return kFailure;
+ }
+
// Decode.
if (!count) {
@@ -849,7 +852,9 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessRLEData() {
(is_top_down_ ? (coord_.Y() < (parent_->Size().Height() - 1))
: (coord_.Y() > 0)))
buffer_->SetHasAlpha(true);
- ColorCorrectCurrentRow();
+ if (!is_past_end_of_image) {
+ ColorCorrectCurrentRow();
+ }
// There's no need to move |coord_| here to trigger the caller
// to call SetPixelsChanged(). If the only thing that's changed
// is the alpha state, that will be properly written into the
@@ -1061,6 +1066,13 @@ void BMPImageReader::ColorCorrectCurrentRow() {
const ColorProfileTransform* const transform = parent_->ColorTransform();
if (!transform)
return;
+ int decoder_width = parent_->Size().Width();
+ // Enforce 0 ≤ current row < bitmap height.
+ CHECK_GE(coord_.Y(), 0);
+ CHECK_LT(coord_.Y(), buffer_->Bitmap().height());
+ // Enforce decoder width == bitmap width exactly. (The bitmap rowbytes might
+ // add a bit of padding, but we are only converting one row at a time.)
+ CHECK_EQ(decoder_width, buffer_->Bitmap().width());
ImageFrame::PixelData* const row = buffer_->GetAddr(0, coord_.Y());
const skcms_PixelFormat fmt = XformColorFormat();
const skcms_AlphaFormat alpha =
@@ -1069,7 +1081,7 @@ void BMPImageReader::ColorCorrectCurrentRow() {
: skcms_AlphaFormat_Unpremul;
const bool success =
skcms_Transform(row, fmt, alpha, transform->SrcProfile(), row, fmt, alpha,
- transform->DstProfile(), parent_->Size().Width());
+ transform->DstProfile(), decoder_width);
DCHECK(success);
buffer_->SetPixelsChanged(true);
}