CVE-2026-8570
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
fortest/mjsunit/maglev/regress-490353576.js |
modified | |
iftest/mjsunit/maglev/regress-490353576.js |
modified |
Files Changed
src/maglev/maglev-interpreter-frame-state.cctest/mjsunit/maglev/regress-490353576.js
Patch
From 54fec2bb063997d5f545c90b8b342b5d620c994f Mon Sep 17 00:00:00 2001
From: Darius Mercadier <dmercadier@chromium.org>
Date: Tue, 17 Mar 2026 11:20:30 +0100
Subject: [PATCH] [maglev] Fix backedge Smi type recording
https://crrev.com/c/7633545 tried to make sure that we call
SetUseRequiresSmi when the backedge of a Phi has Smi type, but it was
using the static type of the backedge rather than its KNA type. For
loop phis, it's more or less the same, but for non-loop phis, the
static type is typically Any, whereas the KNA type is populated as
soon as a CheckedSmiUntag is encountered (as is the case in the
repro).
Fixed: 490353576
Change-Id: I4ed65d4f3791c3c9b4307cf9997c2367f8dfbf56
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7665886
Auto-Submit: Darius Mercadier <dmercadier@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#105897}
---
diff --git a/src/maglev/maglev-interpreter-frame-state.cc b/src/maglev/maglev-interpreter-frame-state.cc
index 595d75c..2d3a2f9 100644
--- a/src/maglev/maglev-interpreter-frame-state.cc
+++ b/src/maglev/maglev-interpreter-frame-state.cc
@@ -1000,13 +1000,13 @@
return;
}
DCHECK_EQ(result->owner(), owner);
- NodeType type =
+ NodeType unmerged_type =
unmerged_aspects.GetTypeUnchecked(builder->broker(), unmerged);
unmerged = EnsureTagged(builder, unmerged_aspects, unmerged,
predecessors_[predecessors_so_far_]);
result->set_input(predecessor_count_ - 1, unmerged);
- result->merge_post_loop_type(type);
+ result->merge_post_loop_type(unmerged_type);
// We've just merged the backedge, which means that future uses of this Phi
// will be after the loop, so we can now promote `post_loop_type` to the
// regular `type`.
@@ -1021,7 +1021,7 @@
// sminess.
if (result->uses_require_smi()) {
unmerged_phi->SetUseRequiresSmi();
- } else if (NodeTypeIs(unmerged_phi->type(), NodeType::kSmi)) {
+ } else if (NodeTypeIs(unmerged_type, NodeType::kSmi)) {
// The backedge has Smi type, but it's possible that this is only true
// because {result} itself is eventually known to be a Smi, thanks to for
// instance a CheckedSmiUntag. If we don't set {use_requires_smi}, then
@@ -1029,6 +1029,10 @@
// invalidating the type of the backedge, and in turn potentially
// invalidating some Phi untagging without us realizing it.
unmerged_phi->SetUseRequiresSmi();
+ } else {
+ // If the static type of {unmerged_phi} was kSmi, we should have gone into
+ // the branch above and called SetUseRequiresSmi.
+ DCHECK(!NodeTypeIs(unmerged_phi->type(), NodeType::kSmi));
}
if (result->uses_require_heap_object()) {
unmerged_phi->SetUseRequiresHeapObject();
diff --git a/test/mjsunit/maglev/regress-490353576.js b/test/mjsunit/maglev/regress-490353576.js
new file mode 100644
index 0000000..c912a2c
--- /dev/null
+++ b/test/mjsunit/maglev/regress-490353576.js
@@ -0,0 +1,21 @@
+// 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: --no-concurrent-recompilation --maglev-untagged-phis
+
+function foo() {
+ let x = 0;
+ var y = 0x4e000000;
+ for (let i = 0; i < 250; i++) {
+ if (i == 100) {
+ x = y;
+ }
+ delete ArrayBuffer[x];
+ x | 0;
+ }
+
+ return x;
+}
+
+assertEquals(1308622848, foo());
Regression Test / PoC
diff --git a/test/mjsunit/maglev/regress-490353576.js b/test/mjsunit/maglev/regress-490353576.js
new file mode 100644
index 0000000..c912a2c
--- /dev/null
+++ b/test/mjsunit/maglev/regress-490353576.js
@@ -0,0 +1,21 @@
+// 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: --no-concurrent-recompilation --maglev-untagged-phis
+
+function foo() {
+ let x = 0;
+ var y = 0x4e000000;
+ for (let i = 0; i < 250; i++) {
+ if (i == 100) {
+ x = y;
+ }
+ delete ArrayBuffer[x];
+ x | 0;
+ }
+
+ return x;
+}
+
+assertEquals(1308622848, foo());
Original Bug Report
V8 correctness failure in sources: d3
Detailed Report: https://clusterfuzz.com/testcase?key=5547061260779520
Fuzzer: foozzie_js_fuzzer Job Type: v8_foozzie_v2 Platform Id: linux
Crash Type: V8 correctness failure Crash Address: Crash State: sources: d3
Sanitizer: address (ASAN)
Regressed: https://clusterfuzz.com/revisions?job=v8_foozzie_v2&range=105097:105098
Reproducer Testcase: https://clusterfuzz.com/download?testcase_id=5547061260779520
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.