Skip to content

[v24.x] deps: backport V8 HeapNumber materialization fix - #66567

Open
inoway46 wants to merge 228 commits into
nodejs:v24.x-stagingfrom
inoway46:backport-v24-maglev-heapnumber
Open

inoway46 wants to merge 228 commits into
nodejs:v24.x-stagingfrom
inoway46:backport-v24-maglev-heapnumber

Conversation

@inoway46

@inoway46 inoway46 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Backport v8/v8@7d5eb1d to fix returned objects sharing mutable double fields, as reported in #66457 (CVE-2026-85045).

The upstream regression fails on v24.21.0 and passes with this backport.

The v26.x backport landed in 1a33e91 (#66566).

Refs: #66457

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/gyp
  • @nodejs/security-wg
  • @nodejs/v8-update

@nodejs-github-bot nodejs-github-bot added build Issues and PRs related to Node.js builds or CI infrastructure. needs-ci PRs that need a full CI run. v24.x Issues that can be reproduced on v24.x or PRs targeting the v24.x-staging branch. v8 engine Issues and PRs related to the V8 dependency. labels Oct 7, 2026
@inoway46
inoway46 marked this pull request as ready for review October 7, 2026 10:18
@aduh95

aduh95 commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Shouldn't this land on Current first?

@inoway46

Copy link
Copy Markdown
Contributor Author

Agreed, #66566 should land first.

@inoway46
inoway46 force-pushed the backport-v24-maglev-heapnumber branch from 1a48a0f to 4fa345f Compare October 11, 2026 08:50
@aduh95
aduh95 marked this pull request as draft October 11, 2026 09:31
@inoway46
inoway46 marked this pull request as ready for review October 12, 2026 15:54
@inoway46

Copy link
Copy Markdown
Contributor Author

The v26.x backport has landed in 1a33e91. I've marked this ready for review.

@codecov

codecov Bot commented Oct 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.50%. Comparing base (9e39360) to head (4fa345f).
⚠️ Report is 591 commits behind head on v24.x-staging.

Additional details and impacted files
@@                Coverage Diff                @@
##           v24.x-staging   #66567      +/-   ##
=================================================
+ Coverage          90.31%   92.50%   +2.19%     
=================================================
  Files                711      371     -340     
  Lines             228425   165729   -62696     
  Branches           43160    25996   -17164     
=================================================
- Hits              206293   153313   -52980     
+ Misses             14090    12108    -1982     
+ Partials            8042      308    -7734     

see 549 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@inoway46

inoway46 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor Author

@aduh95 @richardlau This fix shipped in v26.12.0 on October 14, so it has now been two weeks in a Current release. Could we consider landing this v24 backport?

aduh95 and others added 16 commits October 28, 2026 19:31
Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#63790
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Signed-off-by: avivkeller <me@aviv.sh>
PR-URL: nodejs#64830
Fixes: nodejs#58887
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Upgrades the experimental tag filter introduced by stage 1 to accept a
boolean expression instead of a literal tag name.

Grammar: `and`/`&&`, `or`/`||`, `not`/`!`, parentheses for grouping,
and `*` wildcards inside identifiers. Standard precedence
(`not > and > or`); binary operators are left-associative. Word forms
require whitespace separation; punctuation forms do not. Untagged
tests evaluate `false` for any include expression and `true` for
`not X`, so excluding tags does not accidentally remove untagged
tests.

The flag and `testTagFilters` option are still repeatable; multiple
expressions still AND together. Malformed expressions fail fast at
the parent process at startup.

Tag value validation tightens to reject whitespace, operator
characters (`& | ! ( ) *`), and the reserved words `and`/`or`/`not`
in any casing - a breaking change relative to the stage 1 ship,
acceptable at Stability 1.0 (Early development).

Signed-off-by: atlowChemi <chemi@atlow.co.il>
PR-URL: nodejs#63054
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
A portable compile cache is meant to be reused wherever the same module
layout is found, which includes being generated once (at build time,
say) and shipped read-only with an application for whoever runs it. On
platforms with uids the cache subdirectory is suffixed with the uid of
the user who created it, so such a cache is only ever found by that one
user. Omit the suffix in portable mode: a user who cannot write to the
directory still reads it, and a failed write is only a cache miss.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65293
Reviewed-By: James M Snell <jasnell@gmail.com>
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode/Opus
PR-URL: nodejs#65309
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
The helpers report the command, both streams, and the exit condition
on failure, so mismatches are diagnosed consistently across tests.

Signed-off-by: greenhead <greenheadhq@gmail.com>
PR-URL: nodejs#65552
Refs: nodejs#65377
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#65572
Refs: https://github.com/nodejs/node/pull/65552/changes#r3862720795
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
`uvimpl::Work::AfterThreadPoolWork()` and the thread-safe function's
`DispatchOne()` and `Finalize()` opened an
`AsyncResource::CallbackScope` with only a `HandleScope`.
`InternalCallbackScope` expects the resource's environment context to
be entered and otherwise asserts that `Environment::GetCurrent(isolate)`
is that environment, so with two environments on one isolate an addon's
async work completion or thread-safe function call aborted the process
whenever the other environment's context was current when the loop ran
the callback.

Enter the node-api env's context first, as `CallFinalizer()` and the
zlib and WebCrypto thread pool callbacks already do. In `Finalize()` the
scope covers only the finalizer call, since `MaybeDelete()` can free
the env whose persistent handle `context()` returns.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65406
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Pass input, output, and version values through environment variables
instead of expanding them into shell source. Split benchmark
categories and PR numbers into arrays to retain separate arguments.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: nodejs#66013
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
PR-URL: nodejs#65813
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Remove allocations and repeated work performed for every request:

- reuse a per-connection updateOutgoingData closure and a shared
  'finish' listener instead of binding two functions per request,
  reaching resOnFinish through the connection state stored on the
  response
- cache the ServerResponse options object per server (custom response
  classes keep receiving a fresh object)
- check for Host, Expect, Content-Length and Transfer-Encoding by
  scanning rawHeaders instead of materializing req.headers, which was
  built (with per-name toLowerCase calls) for every request even when
  the application never reads it
- cache the rendered status line per status code when the reason
  phrase is the default, skipping its character validation
- cache the complete 'Date: ...' header line in the utcDate cache and
  the keep-alive header pair for the current server settings
- compute the lenient-validation option chain once per message

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#65802
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
type-long-settimeout.any.js and type-long-setinterval.any.js arm
setTimeout(assert_unreached, 100) as a guard. Under load it can fire
after done(), and the resulting uncaught exception can reach the WPT
runner before the completion message, failing the spec.

Use a script modifier to clear the guard timer from a completion
callback, for these two fixtures only. The guard still fails the test
when done() is never called.

Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>
PR-URL: nodejs#63106
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Signed-off-by: Tim Perry <pimterry@gmail.com>
PR-URL: nodejs#66093
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
libuv reports the event loop metrics exposed through
`performance.nodeTiming.uvMetricsInfo` as `uint64_t` counters, but
they were copied into an `Int32Array` (and, before that, converted
using `v8::Integer::New()`), so they wrapped around after 2^31 on
long-running processes.

Store the metrics in a `Float64Array` instead. Values are now exact
up to `Number.MAX_SAFE_INTEGER`.

Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#66094
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
`performanceNodeTiming.uvMetricsInfo` is a property, not a method, so
document its value using `Type:` rather than `Returns:`.

Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#66094
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
`performance.nodeTiming.uvMetricsInfo` returns the libuv event loop
metrics as numbers, which are only exact up to
`Number.MAX_SAFE_INTEGER`. Add `uvMetricsInfoBigInt`, which returns
the same metrics as bigints backed by `uint64_t` storage, carrying the
full 64-bit range reported by libuv.

A single native call fills both a `Float64Array` and a
`BigUint64Array`, so `uvMetricsInfo` does not pay for bigint
allocation and conversion. The new property is omitted from
`toJSON()`, as `JSON.stringify()` cannot serialize bigints.

Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#66094
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
mcollina and others added 28 commits October 28, 2026 19:32
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#66436
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: James M Snell <jasnell@gmail.com>
Fix several issues with `Utf8Stream` flushing:

* `flush()` now writes buffered data regardless of `minLength`
  and invokes the callback only after pending writes complete,
  including when `minLength` is zero and a write is in flight.
* Multiple concurrent `flush()` calls are tracked correctly and
  `end()` waits for pending flushes before closing.
* `flushSync()` throws `ERR_INVALID_STATE` if called while an
  asynchronous write is in progress instead of corrupting output.
* Periodic flushes no longer stack up while a flush is pending.
* `fsync` is skipped for stdout/stderr file descriptors.
* `reopen()`, `end()` and `destroy()` behave correctly when the
  stream is destroyed while still opening.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: nodejs#66473
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#66599
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Copy validated header names directly into the shallow result instead
of using ObjectAssign on the internal null-prototype map.

Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
PR-URL: nodejs#66592
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
main() read `buf` instead of `buffer`, so every run measured
Buffer.allocUnsafeSlow() even when labeled buffer=fast. Also benchmark
the slow variant and trim the byteLength matrix.

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#66604
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
A failing todo subtest does not fail its parent, so the parent suite was
recorded as passed in the rerun state file along with its children. On
the next run the suite was replayed synthetically and the failing todo
subtest was marked as passed instead of being rerun.

Do not record a passed test whose descendant failed, so the suite body
runs again while passing siblings are still replayed from their own
entries. Document that a failing todo test counts as not yet passed.

Signed-off-by: Barak <26878518+barakor@users.noreply.github.com>
PR-URL: nodejs#66605
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
The data is already a random Buffer, so passing it through
TextEncoder decoded it as UTF-8 and re-encoded it, making
subtle.digest hash a different and larger input than createHash.

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#66608
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
When the last consumer of a share() or shareSync() detached, the min
cursor fell back to the end of the buffer, so every buffered entry was
trimmed, including entries that the detaching consumer had not read.
The source had already produced that data, so consumers that attached
later silently skipped it.

Keep the buffer while there are no consumers, as broadcast() already
does, so late-joining consumers start at the oldest entry still in the
buffer. Document that the source stays open until the share is
cancelled or disposed.

Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#66483
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
When an async source yielded an already-batched Uint8Array[] value,
from() passed it through as-is, however large it was. Every other
input shape (a sync source, or an array passed to from() or
fromSync() directly) splits such batches into batches of at most 128
chunks, which bounds the memory transforms must allocate per batch.

Apply the same bound to async sources. Batches within the bound are
still passed through without copying.

Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#66483
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
The ERR_INVALID_ARG_TYPE messages for async iterable and promise inputs
read "must be an a synchronous input (not AsyncIterable)", because the
error formatter adds "an" to expected-type strings that contain
uppercase letters. Rephrase them in lowercase.

Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#66483
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
PR-URL: nodejs#66620
Refs: simdjson/simdjson#2913
Refs: nodejs#66495
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Signed-off-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com>
PR-URL: nodejs#65750
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Signed-off-by: lazerg <lazerg2@gmail.com>
Assisted-by: Claude Code
PR-URL: nodejs#66565
Fixes: nodejs#66562
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Jacob Smith <jacob@frende.me>
AbortSignal.any() copies the source WeakRefs of a composite input into
the new composite, so nested composites share them. Those WeakRefs were
also used as the unregister tokens for the registrations that prune a
composite's sources once they are collected. When an inner composite
was collected first, its cleanup therefore also unregistered the outer
composite from the same sources. An observed outer composite then
stayed in gcPersistentSignals, together with its listeners, even after
all of its sources were gone and nothing could abort it anymore.

Use each composite's own WeakRef as the unregister token instead, so
collecting one composite only removes its own registrations.

Fixes: nodejs#66612
Refs: nodejs#62367
Assisted-by: Claude Code
Signed-off-by: journaltraces <kxenk@protonmail.com>
PR-URL: nodejs#66617
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Pulls in nodejs/node-pr-labeler#20, which counts each subsystem once
before applying the four-subsystem limit that collapses labels into
`lib / src`. Until now any PR touching three or more files under a
two-label rule (e.g. `src/quic/`, `src/crypto/`) was collapsed even
though it only touched one subsystem.

Signed-off-by: Soul Lee <alus20x@gmail.com>
PR-URL: nodejs#66606
Refs: nodejs/node-pr-labeler@dfe5eb3
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Add deps/v8/** to the QUIC workflow's pull request path filter so
V8 updates trigger its build and tests.

Assisted-by: Codex
Signed-off-by: inoway46 <inoueyuya416@gmail.com>
PR-URL: nodejs#66602
Refs: nodejs#66537
Refs: https://github.com/nodejs/node/actions/runs/37675498427/job/112978479932
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reuse the values array instead of allocating a second result array.

Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
PR-URL: nodejs#66488
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Tim Perry <pimterry@gmail.com>
PR-URL: nodejs#66663
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
PR-URL: nodejs#66655
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
In the non-default parse() path, a key with more than one percent
escape could corrupt non-ASCII characters in its value.

Keep key characters out of the value's encoding check.

Assisted-by: claude:opus-5.5
Signed-off-by: vedchaudhari <vedc2853@gmail.com>
PR-URL: nodejs#66553
Refs: nodejs#66175
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
A source without pull() has nothing observable left to do in its
post-start step, since the started flag only gates calls into the pull
algorithm. Set the flag right away instead of from a microtask, so a
push-style ReadableStream allocates neither the closure nor the task
and is not kept alive until the next microtask checkpoint.

pipeTo and tee hold the only references to their reader and writer, so
their [[closedPromise]] records are never observed as promises. Install
the watchers as the records themselves, as pipeTo's ready hook already
does, instead of materializing a promise plus reaction per side, and
hand the erroring/release probes one shared pending promise. The tee's
cancel promise is likewise materialized by the first branch cancel.

Microtask ordering is unchanged: each hook enqueues its watcher at the
position the promise reaction would have had.

node benchmark/compare.js --runs 20 over benchmark/webstreams (46 rows,
all others within the confidence interval):

webstreams/creation.js kind='ReadableStream'               ***  +172.40%
webstreams/creation.js kind='ReadableStream.tee'           ***   +20.47%
webstreams/creation.js kind='ReadableStreamBYOBReader'     ***   +15.66%
webstreams/creation.js kind='ReadableStreamDefaultReader'  ***   +14.53%
webstreams/lifecycle.js kind='pipe-to' (40 runs)           **    +10.98%

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#66424
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#66652
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#66649
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Call uv_fs_req_cleanup() before returning for directories, otherwise
the path buffer allocated by uv_fs_stat() leaks on Windows.

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#66555
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Python 3.15 removed CGIHTTPRequestHandler, which WPT pywebsocket3 still
uses. This breaks host configuration in the current undici WPT action.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#66699
Reviewed-By: Mike McCready <66998419+MikeMcC399@users.noreply.github.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#66556
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Backport the Maglev HeapNumber materialization fix to V8 13.6.
Emit a captured HeapNumber with its map and constant numeric value,
using the existing deoptimizer to allocate a fresh box. Reserve a
nonduplicatable object ID for each box. Keep the literal-number helper
for fixed double arrays and captured-object numeric values. No virtual
object slot traversal changes or prerequisite commits are needed.
This mirrors the existing V8 13.6 Turbolev map/value materialization.

Original commit message:

    [maglev] Materialize a fresh HeapNumber per deoptimization

    This matches what Turbolev graph builder already does to Maglev.

    Fixed: 547819997
    Change-Id: Iafc1185ef96db8816db36b295a3a4b7e528f9863
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8255554
    Reviewed-by: Leszek Swirski <leszeks@chromium.org>
    Commit-Queue: Victor Gomes <victorgomes@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#109347}

Refs: v8/v8@7d5eb1d
Refs: nodejs#66457
Refs: https://www.cve.org/CVERecord?id=CVE-2026-85045
Signed-off-by: inoway46 <inoueyuya416@gmail.com>
Assisted-by: Codex
@inoway46
inoway46 force-pushed the backport-v24-maglev-heapnumber branch from 4fa345f to fa476db Compare October 29, 2026 01:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Issues and PRs related to Node.js builds or CI infrastructure. needs-ci PRs that need a full CI run. v8 engine Issues and PRs related to the V8 dependency. v24.x Issues that can be reproduced on v24.x or PRs targeting the v24.x-staging branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.