CVE-2026-19162
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifsrc/heap/factory.cc |
modified | |
TEST_Ftest/unittests/regress/regress-536271629-unittest.cc |
modified |
Files Changed
src/heap/factory.ccsrc/heap/factory.hsrc/runtime/runtime-scopes.cctest/unittests/regress/regress-536271629-unittest.cc
Patch
From 78276f18796f1e4c0698ab217e22af3ec27bbbaf Mon Sep 17 00:00:00 2001
From: Victor Gomes <victorgomes@chromium.org>
Date: Wed, 05 Aug 2026 17:02:28 +0200
Subject: [PATCH] [runtime] Allocate mapped arguments with the sloppy arguments map
NewSloppyArguments went through Factory::NewArgumentsObject, which picks
the strict or the sloppy arguments map from the callee's ScopeInfo, and
then installed the larger fast aliased arguments map on the result. The
allocation size and the final map therefore came from two independent
sources of truth. Pick the map from the mapped arguments path itself.
Bug: 536271629
Change-Id: I0a1185066f6b43e09816d726c488d3846a4830a6
Fixed: 536271629
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8204384
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#109097}
---
diff --git a/src/heap/factory.cc b/src/heap/factory.cc
index 7d674a9..543388d 100644
--- a/src/heap/factory.cc
+++ b/src/heap/factory.cc
@@ -41,7 +41,6 @@
#include "src/numbers/conversions.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/allocation-site-inl.h"
-#include "src/objects/allocation-site-scopes.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/arguments-inl.h"
#include "src/objects/bigint.h"
@@ -4610,11 +4609,13 @@
int length) {
bool strict_mode_callee = is_strict(callee->shared()->language_mode()) ||
!callee->shared()->has_simple_parameters();
- DirectHandle<Map> map = strict_mode_callee
- ? isolate()->strict_arguments_map()
- : isolate()->sloppy_arguments_map();
- AllocationSiteUsageContext context(isolate(), Handle<AllocationSite>(),
- false);
+ return strict_mode_callee ? NewStrictArgumentsObject(callee, length)
+ : NewSloppyArgumentsObject(callee, length);
+}
+
+Handle<JSObject> Factory::NewStrictArgumentsObject(
+ DirectHandle<JSFunction> callee, int length) {
+ DirectHandle<Map> map = isolate()->strict_arguments_map();
DCHECK(!isolate()->has_exception());
Handle<JSObject> result = NewJSObjectFromMap(map);
DirectHandle<Smi> value(Smi::FromInt(length), isolate());
@@ -4622,12 +4623,23 @@
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Assert();
- if (!strict_mode_callee) {
- Object::SetProperty(isolate(), result, callee_string(), callee,
- StoreOrigin::kMaybeKeyed,
- Just(ShouldThrow::kThrowOnError))
- .Assert();
- }
+ return result;
+}
+
+Handle<JSObject> Factory::NewSloppyArgumentsObject(
+ DirectHandle<JSFunction> callee, int length) {
+ DirectHandle<Map> map = isolate()->sloppy_arguments_map();
+ DCHECK(!isolate()->has_exception());
+ Handle<JSObject> result = NewJSObjectFromMap(map);
+ DirectHandle<Smi> value(Smi::FromInt(length), isolate());
+ Object::SetProperty(isolate(), result, length_string(), value,
+ StoreOrigin::kMaybeKeyed,
+ Just(ShouldThrow::kThrowOnError))
+ .Assert();
+ Object::SetProperty(isolate(), result, callee_string(), callee,
+ StoreOrigin::kMaybeKeyed,
+ Just(ShouldThrow::kThrowOnError))
+ .Assert();
return result;
}
diff --git a/src/heap/factory.h b/src/heap/factory.h
index 4c17e36..4013c8a 100644
--- a/src/heap/factory.h
+++ b/src/heap/factory.h
@@ -738,6 +738,12 @@
Handle<JSObject> NewArgumentsObject(DirectHandle<JSFunction> callee,
int length);
+ Handle<JSObject> NewStrictArgumentsObject(DirectHandle<JSFunction> callee,
+ int length);
+
+ Handle<JSObject> NewSloppyArgumentsObject(DirectHandle<JSFunction> callee,
+ int length);
+
// Allocates and initializes a new JavaScript object based on a
// constructor.
// JS objects are pretenured when allocated by the bootstrapper and
diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc
index fe8a3ed..d411795 100644
--- a/src/runtime/runtime-scopes.cc
+++ b/src/runtime/runtime-scopes.cc
@@ -554,7 +554,7 @@
CHECK(!IsDerivedConstructor(callee->shared()->kind()));
CHECK(callee->shared()->has_simple_parameters());
DirectHandle<JSObject> result =
- isolate->factory()->NewArgumentsObject(callee, argument_count);
+ isolate->factory()->NewSloppyArgumentsObject(callee, argument_count);
// Allocate the elements if needed.
const uint32_t parameter_count =
@@ -573,8 +573,10 @@
isolate->factory()->NewSloppyArgumentsElements(
mapped_count, context, arguments, AllocationType::kYoung);
- result->set_map(isolate,
- isolate->native_context()->fast_aliased_arguments_map());
+ Tagged<Map> aliased_map =
+ isolate->native_context()->fast_aliased_arguments_map();
+ CHECK_EQ(aliased_map->instance_size(), result->map()->instance_size());
+ result->set_map(isolate, aliased_map);
result->set_elements(*parameter_map);
// Loop over the actual parameters backwards.
diff --git a/test/unittests/regress/regress-536271629-unittest.cc b/test/unittests/regress/regress-536271629-unittest.cc
index 57c944d..a64907f 100644
--- a/test/unittests/regress/regress-536271629-unittest.cc
+++ b/test/unittests/regress/regress-536271629-unittest.cc
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/execution/isolate-inl.h"
#include "src/execution/isolate.h"
+#include "src/objects/contexts-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/scope-info.h"
#include "src/objects/shared-function-info-inl.h"
@@ -56,5 +58,18 @@
EXPECT_DEATH_IF_SUPPORTED(RunJS("duplicate(1, 2)"), "");
}
+// The mapped arguments path allocates with the sloppy arguments map and then
+// installs the fast aliased arguments map, so the two must have the same
+// instance size.
+TEST_F(SloppyArgumentsScopeInfoTest, ArgumentsMapInstanceSizes) {
+ v8::HandleScope scope(isolate());
+ Tagged<NativeContext> context = i_isolate()->raw_native_context();
+
+ const int sloppy_size = context->sloppy_arguments_map()->instance_size();
+ CHECK_EQ(sloppy_size, context->fast_aliased_arguments_map()->instance_size());
+ CHECK_EQ(sloppy_size, context->slow_aliased_arguments_map()->instance_size());
+ CHECK_LT(context->strict_arguments_map()->instance_size(), sloppy_size);
+}
+
} // namespace internal
} // namespace v8
Regression Test / PoC
diff --git a/test/unittests/regress/regress-536271629-unittest.cc b/test/unittests/regress/regress-536271629-unittest.cc
index 57c944d..a64907f 100644
--- a/test/unittests/regress/regress-536271629-unittest.cc
+++ b/test/unittests/regress/regress-536271629-unittest.cc
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/execution/isolate-inl.h"
#include "src/execution/isolate.h"
+#include "src/objects/contexts-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/scope-info.h"
#include "src/objects/shared-function-info-inl.h"
@@ -56,5 +58,18 @@
EXPECT_DEATH_IF_SUPPORTED(RunJS("duplicate(1, 2)"), "");
}
+// The mapped arguments path allocates with the sloppy arguments map and then
+// installs the fast aliased arguments map, so the two must have the same
+// instance size.
+TEST_F(SloppyArgumentsScopeInfoTest, ArgumentsMapInstanceSizes) {
+ v8::HandleScope scope(isolate());
+ Tagged<NativeContext> context = i_isolate()->raw_native_context();
+
+ const int sloppy_size = context->sloppy_arguments_map()->instance_size();
+ CHECK_EQ(sloppy_size, context->fast_aliased_arguments_map()->instance_size());
+ CHECK_EQ(sloppy_size, context->slow_aliased_arguments_map()->instance_size());
+ CHECK_LT(context->strict_arguments_map()->instance_size(), sloppy_size);
+}
+
} // namespace internal
} // namespace v8
Original Bug Report
Incompatible Cached `ScopeInfo` Causes a Sloppy-Arguments Underallocation and Caged ARW
Security Report: Incompatible Cached ScopeInfo Causes a Sloppy-Arguments Underallocation and Caged ARW
Reporter: OpenAI Codex Security
Organization: OpenAI
Component: V8 JavaScript engine (compilation-cache merge, ScopeInfo, sloppy arguments)
Affected Area: Script::FindSharedFunctionInfo, own-ScopeInfo reuse, Factory::NewArgumentsObject, NewSloppyArguments
Bug Class: stale semantic metadata -> undersized heap object -> following-object Map read/write -> arbitrary read/write inside the V8 sandbox
Summary
V8 can publish one SharedFunctionInfo whose current bytecode, formal count,
and duplicate-parameter bit came from a current simple sloppy function while
its own ScopeInfo came from a cached non-simple function at the same source
position. The merge validates source-range identity, scope type, and Context
length, but not the parameter semantics later consumed by the arguments
runtime.
Runtime_NewSloppyArguments then reasons about this compound state through two
different sources of truth. Factory::NewArgumentsObject asks the stale
ScopeInfo::HasSimpleParameters bit and allocates a 16-byte strict arguments
object. The mapped-arguments path asks the current SFI and active frame for
their formal/actual counts and subsequently installs the 20-byte
fast_aliased_arguments_map. The only assertion that these states agree is a
DCHECK.
The resulting arguments.callee field is physically the next allocation’s
Map word. The supplied exploit changes an independent object
word from 0x1111 to 0x12345678, restores its genuine Map, and then turns
the same primitive into a 4-GiB DataView covering the V8 pointer-compression
cage. No experimental V8 feature is involved.
The final exploit PoC is an HTML entry point with one service-worker sidecar. The HTML contains all exploit JavaScript and generates the equal-length A/B bodies at runtime. The worker only persists and serves the normal code-cache carrier. No native addresses, target offsets, URL tuning arguments, or other exploit files are used.
The same attachment exposes an optional controlled-fault exploit with
?crash=1. After the full cage primitive exists, it writes the value
0x41424344 to cage offset 0x41424344. In a measured
Chrome for Testing 150.0.7871.128 run, the observer and browser crash log were:
page observer (JavaScript POST immediately before the cage write):
{"phase":"cage-write-crash-armed","success":true,"offset":"0x41424344","value":"0x41424344"}
Chrome native crash log (stderr):
Received signal 11 SEGV_ACCERR 3d5941424344
r9: 0000000041424344 r11: 0000000041424344
r12: 00003d5900000000 r14: 00003d5900000000
cr2: 00003d5941424344
The randomized cage base in that run was 0x3d5900000000; the faulting
address is exactly cage_base + 0x41424344.
Impact
The confirmed primitive is arbitrary read/write throughout the 4-GiB V8 heap cage. The result is not merely reading one adjacent backing store:
deep-sentinel.success = true
cageLength = 4294967296
ROOT_OBJECT.p0 before = 4369 (0x1111)
ROOT_OBJECT.p0 written = 305419896 (0x12345678)
read32(ROOT_OBJECT.p0) = 610839792 (raw tagged word)
The first word change is independently selected and occurs before construction
of the cage-wide view. The PoC then leaks/repairs genuine V8 Maps, forges a
branded JSArrayBuffer/DataView, and exports read32, write32, and
addrof. This is the full primitive required by the V8 sandbox threat model.
Root Cause (High Level)
Three independently derived facts are combined without one final compatibility check:
allocation map and size:
SFI.scope_info.HasSimpleParameters() == false
-> strict_arguments_map -> 0x10-byte object
runtime path and final map:
current duplicate/simple bytecode executes CreateMappedArguments
current formal count > 0 and active actual count > 0
-> fast_aliased_arguments_map -> 0x14-byte object
release validation:
only DCHECK(shared.has_simple_parameters())
The compiler-cache producer makes the contradiction reachable from a normal
page. A Service Worker stores two bodies descended from one
Response.clone() relationship. The stored victim has B’s body but preserves
the cached association used for A. Lazy partial deserialization and own-scope
reuse accept same-position child/scope identities without semantic equality.
B’s current q therefore runs with A’s non-simple ScopeInfo.
The memory-safety root is the last transition: V8 allocates one physical object with one Map and immediately installs a larger Map selected from independent metadata. Fixing the cache producer alone would close this known remote route but would leave an unsafe release-mode consumer of corrupted or inconsistent SFI state.
Affected Versions
The final HTML exploit was confirmed on the V8 lines through canonical unchanged x64 release products:
V8 15.0 branch used by Chrome 150.0.7871.128
V8 revision: 2b2f69158528fdd9d86b778cfcc2d0a1c4f8c59f
V8 15.1 branch used at Chromium position 1654411
V8 revision: f479186c16abdb6fa05539fe957bb84deee830df
canonical shell: Chrome for Testing 151.0.7922.34
(same Chromium position and V8 revision as the .29 product)
The exact runtime checks used these unmodified binary hashes:
| Engine validation | Canonical product | Chrome/Chromium position | Binary SHA-256 | Result |
|---|---|---|---|---|
| V8 15.0.1240245 | CFT 150.0.7871.128 | 1639810 | 0f4ce823bf8765f902f46668c2cb3d9c6e3eaf0d3b98a78fe55fc638b78acaa4 |
4-GiB cage R/W and selected object-word write/readback |
| V8 15.1.206.8 | CFT 151.0.7922.34 | 1654411 | 0b20b130e7edd9dd51873be867761295fe0cfad490c2b9a64f95bd3cfc08fa71 |
4-GiB cage R/W and selected object-word write/readback |
Current upstream main at V8 revision
0747938f5c0d8df34b52fccea2f81fb5e5b1e163
remains vulnerable. Source inspection shows that
Script::FindSharedFunctionInfo
still accepts the cached SFI by function identity and source positions, and
Scope::AllocateScopeInfosRecursively
still reuses the cached own ScopeInfo after checking only scope type,
Context presence, and Context length. Main does not compare the
simple-parameter semantic bit consumed by
Factory::NewArgumentsObject,
while NewSloppyArguments
still installs the larger aliased-arguments Map with only a debug assertion
connecting these facts. The complete underallocation path therefore remains
present in current main.
There are two relevant historical boundaries:
- Semantically compatible
ScopeInforeuse was introduced in 2024. The blind own-ScopeInfopath entered in V867dd629e34bb45157ade97d98d374c43ae71dd11. After an interrupted rollout, it has been continuously enabled in sampled Stable releases from the Chrome 134 / V8 13.4 family through current main. - The unsafe strict-sized allocation followed by unconditional aliased-Map
installation was introduced by
c8211b64cdee1dc71fa91945c8e5fa9880fcee2fon 2015-07-02. It is present from V8 4.5 through current main. The exact remote PoC has the narrower modern compilation-cache/ScopeInfofloor.
Detailed Analysis
Stale Own-Scope Metadata Survives the Merge
ScopeInfo::UniqueIdInScript() primarily identifies a scope by its source
position. Scope::AllocateScopeInfosRecursively accepts a cached object after
checking only scope_type, HasContext(), and ContextLength(). The
background finalization path can then install the old own ScopeInfo directly.
The missing comparison covers the exact fields used later: simple/non-simple
parameters, parameter count, duplicate parameter ownership, context-local
names and modes, initialization/assignment flags, context-cell use, and each
ContextLocalParameterNumber.
The A/B functions in the PoC deliberately agree on every checked structural
quantity. Both are sloppy FUNCTION_SCOPEs at identical ranges, both need a
length-3 Context, and both have 32,767 formal positions. A has distinct
non-simple formals; B repeats one simple formal name. The merged result cannot
be produced by one valid parse:
current body and bytecode: B, including CreateMappedArguments
current SFI counts/flags: B
attached own ScopeInfo: A, including HasSimpleParameters == false
The Factory Allocates the Smaller Physical Object
Current main’s
Factory::NewArgumentsObject
selects the allocation Map from the stale accessor:
bool strict_mode_callee = is_strict(callee->shared()->language_mode()) ||
!callee->shared()->has_simple_parameters();
DirectHandle<Map> map = strict_mode_callee
? isolate()->strict_arguments_map()
: isolate()->sloppy_arguments_map();
Handle<JSObject> result = NewJSObjectFromMap(map);
With pointer compression, strict arguments have one in-object property
(length) and occupy 16 bytes. Fast sloppy arguments have length and
callee and occupy 20 bytes.
The Runtime Installs the Larger Map
Current main’s
NewSloppyArguments
contains the only semantic check as a debug assertion:
DCHECK(callee->shared()->has_simple_parameters());
DirectHandle<JSObject> result =
isolate->factory()->NewArgumentsObject(callee, argument_count);
It independently obtains the current formal count. When actual and formal counts are both nonzero, the release build executes:
result->set_map(isolate,
isolate->native_context()->fast_aliased_arguments_map());
result->set_elements(*parameter_map);
There is no CHECK that the physical allocation is at least the final Map’s
instance size. The two large backing objects are arranged immediately above
the regular-object threshold, so they go to young large-object space and do
not advance the regular allocation buffer. The next regular object starts at
A+0x10, exactly where the new Map describes A.callee.
From One Following-Object Word to Cage-Wide ARW
The PoC first leaks a genuine strict-arguments Map and transfers it through the
selected callee word. It uses a regular object with one in-object slot as the
independent witness, then restores its original Map. Repeating the same
physical layout around genuine objects and an ArrayBuffer leaks the needed
compressed pointers and places a genuine DataView Map on a 4-GiB view. The
underlying ArrayBuffer is still inside the V8 sandbox; the primitive’s scope
is exactly the sandbox’s 4-GiB heap cage.
Exploitation Strategy
- Register the sidecar Service Worker and store equal-length A/B bodies under the same CacheStorage URL.
- Execute A, keep the nested children active, and force a catchable last-resort collection with maximum resizable-ArrayBuffer reservations.
- Automatically navigate to a new document at the same origin after the producer has persisted its cache state.
- Execute the stored B body and obtain B bytecode/SFI paired with A’s
ScopeInfo. - Prime the current generic arguments runtime and place an independent target immediately after the undersized object.
- Use
arguments.calleeas the target’s physical Map word, leak/restore genuine Maps, and construct the cage-wide read/write view.
The navigation creates the current B closures from the persisted cache graph, and the complete producer-to-ARW sequence runs from one page load without user interaction.
Proof of Concept
Attached are the following POC files:
./code-cache-scopeinfo-sloppy-arguments-cage-arw-poc.html
./code-cache-scopeinfo-sloppy-arguments-cache-worker.js.
Serve both from the same loopback directory under those exact filenames. The HTML contains all exploit code; the JavaScript sidecar is only the Service Worker used to preserve and serve the two CacheStorage responses.
Run an HTTP server from the directory containing both attachments. A
loopback HTTP origin is treated as potentially trustworthy for Service Worker
registration; file:// does not work:
python3 -m http.server 8000 --bind 127.0.0.1
Use the unchanged Linux-x64 Chrome for Testing 150.0.7871.128 executable as the primary reproduction target:
CFT=/absolute/path/to/chrome-150.0.7871.128/chrome-linux64/chrome
"$CFT" --version
# Expected: Google Chrome for Testing 150.0.7871.128
PROFILE=$(mktemp -d)
"$CFT" --no-sandbox --user-data-dir="$PROFILE" \
'http://127.0.0.1:8000/code-cache-scopeinfo-sloppy-arguments-cage-arw-poc.html'
The identical attachments were also work without changes on Chrome for Testing 151.0.7922.34 (the 15.1 revision).
The page reloads itself once after its worker activates, runs the producer, and automatically navigates to its consumer. No interaction after opening the link is required.
To produce the fixed-offset crash log with the same attachment, append only
?crash=1, run in a fresh profile, and capture Chrome’s stderr:
PROFILE=$(mktemp -d)
LOG=/tmp/scopeinfo-cage-write-crash.log
timeout --signal=TERM --kill-after=5s 90s \
"$CFT" --headless=new --no-sandbox --disable-dev-shm-usage \
--user-data-dir="$PROFILE" \
'http://127.0.0.1:8000/code-cache-scopeinfo-sloppy-arguments-cage-arw-poc.html?crash=1' \
2>&1 | tee "$LOG"
grep -E 'Received signal|SEGV_|cr2:' "$LOG"
The page observer recorded the first line; Chrome stderr recorded the native fault lines:
page observer (JavaScript POST immediately before the cage write):
{"phase":"cage-write-crash-armed","success":true,"offset":"0x41424344","value":"0x41424344"}
Chrome native crash log (stderr):
Received signal 11 SEGV_ACCERR 3d5941424344
r9: 0000000041424344 r11: 0000000041424344
r12: 00003d5900000000 r14: 00003d5900000000
cr2: 00003d5941424344
The crash sink runs only after cageLength == 4294967296 and the selected
object-word write/readback. It changes only the final address from an ordinary
valid cage object offset to the fixed offset above.
This reproduction uses Chrome’s production CacheStorage and Service Worker code-cache features to reach V8’s compilation-cache merge from a loaded page.
Suggested Fix
- Preserve the
ScopeInfoderived from the current AST unless every semantic flag and variable/parameter record of the cached object is equal. Do not install own scope metadata by UID/range/type/Context length alone. - In
NewSloppyArguments, promote the simple-parameter invariant to a sandbox hard check before any allocation. - Derive initial and final arguments Maps from one validated runtime mode, and
require
actual_size >= final_map->instance_size()in release. - Reject a
SharedFunctionInfowhose active bytecode arguments mode, duplicate bit, formal count, attachedScopeInfo, and Context length do not form one parse-valid state.
Regression coverage should deserialize a cached same-range function whose simple-parameter bit alone differs, then execute it in a release build with actual parameters. The expected result is current B semantics or deterministic fail-stop before allocation—never a Map transition that enlarges an object.
Reporter Credit
OpenAI Codex Security (amyb)
Disclaimer
This information is being shared by OpenAI solely for the purpose of improving security and reducing potential harm. This information is presented as-is. We make no representations or warranties, express or implied, as to the completeness, accuracy, or fitness for any particular purpose of the information. This includes, without limitation any suggestions or ideas presented on how to remedy or mitigate an identified vulnerability, including whether such suggestions or ideas would be effective and/or could have other negative impacts.
OpenAI disclaims any liability for direct or indirect damages arising from the reliance on, or use, misuse, or interpretation of this information. Any references to third-party systems, services, or entities are included solely for identification purposes and do not imply endorsement, responsibility, or attribution.
- http://127.0.0.1:8000/code-cache-scopeinfo-sloppy-arguments-cage-arw-poc.html
- http://127.0.0.1:8000/code-cache-scopeinfo-sloppy-arguments-cage-arw-poc.html?crash=1
- https://github.com/v8/v8/blob/0747938f5c0d8df34b52fccea2f81fb5e5b1e163/src/ast/scopes.cc#L2928-L2952
- https://github.com/v8/v8/blob/0747938f5c0d8df34b52fccea2f81fb5e5b1e163/src/heap/factory.cc#L4612
- https://github.com/v8/v8/blob/0747938f5c0d8df34b52fccea2f81fb5e5b1e163/src/heap/factory.cc#L4612-L4619
- https://github.com/v8/v8/blob/0747938f5c0d8df34b52fccea2f81fb5e5b1e163/src/objects/script.cc#L55-L78
- https://github.com/v8/v8/blob/0747938f5c0d8df34b52fccea2f81fb5e5b1e163/src/runtime/runtime-scopes.cc#L549
- https://github.com/v8/v8/blob/0747938f5c0d8df34b52fccea2f81fb5e5b1e163/src/runtime/runtime-scopes.cc#L550-L580
- https://github.com/v8/v8/commit/0747938f5c0d8df34b52fccea2f81fb5e5b1e163
- https://github.com/v8/v8/commit/67dd629e34bb45157ade97d98d374c43ae71dd11
- https://github.com/v8/v8/commit/c8211b64cdee1dc71fa91945c8e5fa9880fcee2f