CVE-2026-5863
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifsrc/maglev/maglev-graph-builder.cc |
modified |
Files Changed
src/maglev/maglev-graph-builder.ccsrc/maglev/maglev-graph-builder.htest/mjsunit/turbolev/regress-484527367.js
Patch
From b54c7841e2cdb2c3a8c7c315daa41ca99ecd7329 Mon Sep 17 00:00:00 2001 From: Darius Mercadier <[email protected]> Date: Mon, 23 Feb 2026 16:14:11 +0100 Subject: [PATCH] [*lev] Correctly update use counts for nested builtin continuations Fixed: 484527367 Change-Id: I4cda8c1bbb2788fca06b564eae509511aec0957e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7593054 Reviewed-by: Victor Gomes <[email protected]> Auto-Submit: Darius Mercadier <[email protected]> Commit-Queue: Darius Mercadier <[email protected]> Cr-Commit-Position: refs/heads/main@{#105381} --- diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc index 3718e10..832ec14 100644 --- a/src/maglev/maglev-graph-builder.cc +++ b/src/maglev/maglev-graph-builder.cc @@ -1542,19 +1542,19 @@ return caller_details_->deopt_frame; } -namespace { -DeoptFrame* RecursivelyWrapDeoptFrameWithContinuations( - Zone* zone, const DeoptFrame& frame, +DeoptFrame* MaglevGraphBuilder::RecursivelyWrapDeoptFrameWithContinuations( + const DeoptFrame& frame, const MaglevGraphBuilder::LazyDeoptFrameScope* parent_scope) { if (!parent_scope) { - return zone->New<DeoptFrame>(frame); + return zone()->New<DeoptFrame>(frame); } - return zone->New<DeoptFrame>(parent_scope->data(), - RecursivelyWrapDeoptFrameWithContinuations( - zone, frame, parent_scope->parent())); + AddDeoptUseToScopeData(parent_scope->data()); + + return zone()->New<DeoptFrame>(parent_scope->data(), + RecursivelyWrapDeoptFrameWithContinuations( + frame, parent_scope->parent())); } -} // namespace DeoptFrame* MaglevGraphBuilder::GetLatestCheckpointedFrame() { if (in_prologue_) { @@ -1581,7 +1581,7 @@ latest_checkpointed_frame_ = zone()->New<DeoptFrame>( deopt_scope->data(), RecursivelyWrapDeoptFrameWithContinuations( - zone(), *latest_checkpointed_frame_, deopt_scope->parent())); + *latest_checkpointed_frame_, deopt_scope->parent())); } } return latest_checkpointed_frame_; @@ -1603,7 +1603,8 @@ result_location, result_size); } -void MaglevGraphBuilder::AddDeoptUseToScopeData(DeoptFrame::FrameData& data) { +void MaglevGraphBuilder::AddDeoptUseToScopeData( + const DeoptFrame::FrameData& data) { switch (data.tag()) { case DeoptFrame::FrameType::kInterpretedFrame: case DeoptFrame::FrameType::kInlinedArgumentsFrame: diff --git a/src/maglev/maglev-graph-builder.h b/src/maglev/maglev-graph-builder.h index b2d9328..223e447 100644 --- a/src/maglev/maglev-graph-builder.h +++ b/src/maglev/maglev-graph-builder.h @@ -1511,7 +1511,11 @@ void AddDeoptUse(VirtualObject* alloc); void AddNonEscapingUses(InlinedAllocation* allocation, int use_count); - void AddDeoptUseToScopeData(DeoptFrame::FrameData& data); + void AddDeoptUseToScopeData(const DeoptFrame::FrameData& data); + + DeoptFrame* RecursivelyWrapDeoptFrameWithContinuations( + const DeoptFrame& frame, + const MaglevGraphBuilder::LazyDeoptFrameScope* parent_scope); std::optional<VirtualObject*> TryGetNonEscapingArgumentsObject( ValueNode* value); diff --git a/test/mjsunit/turbolev/regress-484527367.js b/test/mjsunit/turbolev/regress-484527367.js new file mode 100644 index 0000000..5766d96 --- /dev/null +++ b/test/mjsunit/turbolev/regress-484527367.js @@ -0,0 +1,28 @@ +// Copyright 2026 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --turbolev + +function __wrapTC(f, permissive = true) { + try { + return f(); + } catch (e) { + } +} + +function foo() { + const arr = __wrapTC(() => []); + function bar(arr1) { + const arr2 = [null,,]; + arr1.forEach(Array.prototype.forEach, arr2); + } + __wrapTC(() => bar(arr)); +} + +%PrepareFunctionForOptimization(foo); +foo.apply(); +foo(); + +%OptimizeFunctionOnNextCall(foo); +foo();
Regression Test / PoC
diff --git a/test/mjsunit/turbolev/regress-484527367.js b/test/mjsunit/turbolev/regress-484527367.js
new file mode 100644
index 0000000..5766d96
--- /dev/null
+++ b/test/mjsunit/turbolev/regress-484527367.js
@@ -0,0 +1,28 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbolev
+
+function __wrapTC(f, permissive = true) {
+ try {
+ return f();
+ } catch (e) {
+ }
+}
+
+function foo() {
+ const arr = __wrapTC(() => []);
+ function bar(arr1) {
+ const arr2 = [null,,];
+ arr1.forEach(Array.prototype.forEach, arr2);
+ }
+ __wrapTC(() => bar(arr));
+}
+
+%PrepareFunctionForOptimization(foo);
+foo.apply();
+foo();
+
+%OptimizeFunctionOnNextCall(foo);
+foo();
Original Bug Report
DCHECK failure in use_count_ > 0 in maglev-ir.h
Detailed Report: https://clusterfuzz.com/testcase?key=5109997302120448
Fuzzer: ochang_js_fuzzer Job Type: linux_asan_d8_v8_arm_dbg Platform Id: linux
Crash Type: DCHECK failure Crash Address: Crash State: use_count_ > 0 in maglev-ir.h
Sanitizer: address (ASAN)
Regressed: https://clusterfuzz.com/revisions?job=linux_asan_d8_v8_arm_dbg&range=105182:105183
Reproducer Testcase: https://clusterfuzz.com/download?testcase_id=5109997302120448
Issue filed automatically.
To reproduce this, please build the target in this report and run it against the reproducer testcase. Please use the GN arguments provided at bottom of this report when building the binary.
If you have trouble reproducing, please also export the environment variables listed under “[Environment]” in the crash stacktrace.
If you have any feedback on reproducing test cases, let us know at https://forms.gle/Yh3qCYFveHj6E5jz5 so we can improve.