Check the normalized SHA algorithm instead of reading the caller hash
name before conversion. This prevents changing getters from bypassing
the supported hash check.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Use only errors captured by the cipher job when converting its result.
Unrelated errors on the event loop thread must not turn a successful
operation into a failure or trigger an assertion.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reject non-ASCII equivalents of registered Web Crypto algorithm names.
Skip the character scan when the input already uses the canonical name.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Read buffer lengths and element sizes from internal slots in
randomFillSync() and randomFill(). Shadowed properties can otherwise
skip filling, change the selected range, or fail a native bounds check.
Use the intrinsic byte length for the getRandomValues() quota check and
keep its delegation to randomFillSync().
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
The reserved root `${os.devNull}/vfs`, which holds the mount points of
all virtual file systems, could not be read: fs calls on it fell through
to the real file system, so nothing could list what was mounted.
While any file system is mounted, serve the root as a read-only
directory. It lists every mount point by the last segment of its path, a
recursive listing descends into each mounted file system, and paths
under it that no mount serves report ENOENT. Creating, removing or
changing entries in it fails with EROFS. When nothing is mounted it does
not exist, as before.
Add vfs.vfsBase(), which returns the path of that directory, so that a
program can read it without spelling the path out.
A mount point cannot be removed or renamed, nor replaced by a rename:
rmdir() and rename() fail with EBUSY, and a recursive rm() empties the
file system and then fails the same way. Before, rmdir() of an empty
mount point reported success without doing anything.
The callback and promise forms of readdir() with `withFileTypes` now
report each Dirent's parentPath as a host path, as readdirSync() did,
instead of the provider-relative one, and split recursive names such as
`dir/file.txt` into their directory and base name. A recursive listing
joins subdirectories with the host separator rather than `/`, which
mixed separators on Windows. realpath() of a mount point no longer
returns it with a trailing separator.
Signed-off-by: Philipp Dunkel <pip@pipobscure.com>
PR-URL: https://github.com/nodejs/node/pull/66140
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Getting the values recorded during an interval requires calling
`reset()`, which removes them for every other user of the histogram,
or copying and subtracting histograms, which silently produces a wrong
result when the source was reset in between.
Add `histogram.diff(other)`, which returns a new read-only `Histogram`
containing the values recorded after `other`, an earlier snapshot of
the histogram, was taken. Neither histogram is changed. Unlike
`subtract()`, it verifies that both histograms have the same layout,
and it throws instead of clamping when `other` contains values that
the histogram does not.
Add `histogram.resetCount`, the number of calls to `reset()` and
`subtract()`, which `snapshot()` copies. `diff()` throws when the
counts differ, so a reset between two snapshots is detected even when
every bucket has since grown past its previous count.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: OpenCode
PR-URL: https://github.com/nodejs/node/pull/66099
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
The native object behind histograms created by `createHistogram()`,
`importHistogram()`, and `snapshot()` did not report the memory of its
HDR histogram to V8. That memory is about 352 KiB with the default
options, and V8 did not take it into account when scheduling garbage
collection. Short-lived histograms could therefore hold on to a large
amount of native memory until an unrelated garbage collection: in a
loop taking 2,000 snapshots, RSS grew by 477 MiB.
Report the size of the native histogram while the object is alive, as
`SlidingWindowHistogram` already does for its chunks. Objects that
share a native histogram after cloning each report its full size.
With this change, RSS grows by 8 MiB in the same loop.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: OpenCode
PR-URL: https://github.com/nodejs/node/pull/66099
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Cloning a histogram with `structuredClone()` or `postMessage()` shares
the native histogram instead of copying it. Capturing the state of a
histogram at a point in time, while other code keeps recording into
it, requires serializing it with `export()` and parsing the result
with `importHistogram()`.
Add `histogram.snapshot()`, which returns a new, independent
`Histogram` containing a copy of the histogram's configuration,
recorded values, `exceeds` count, and EWMA state, without the
serialization round trip. Values cannot be recorded into the returned
histogram. The method is available on all histograms, including
`RecordableHistogram` and `ELDHistogram` instances.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: OpenCode
PR-URL: https://github.com/nodejs/node/pull/66099
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Histograms exported by Node.js v26.9.0 use format version 1, which
rejects unknown keys on import. Adding fields to version 1 data would
therefore break importing it in v26.9.0, even though that release
claims to support version 1.
Introduce format version 2. It has the same layout as version 1, but
unknown keys are ignored on import, so fields can be added to it later
without changing the version again, while older releases reject it
based on the version rather than on the new fields.
`histogram.export()` now produces version 2 data. `importHistogram()`
accepts versions 1 and 2, and imports version 1 data, as well as data
without a version, with the original semantics.
Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66098
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
`importHistogram()` did not check the CBOR major type of keys and
integer values, so other data items were decoded as integers. It also
accepted duplicate keys, silently truncated integers cast to narrower
types, allowed bucket counts that did not fit into an `int64_t`, and
trusted the total count, min, and max, leaving imported histograms in
an inconsistent state when those were absent or did not match the
counts.
Validate major types and value ranges, reject duplicate keys and
non-increasing sparse count indexes, and derive the total count, min,
and max from the counts when they are absent. A total count that is
present must match the counts. Data produced by `histogram.export()`
is unaffected.
Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66098
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
fs.rmSync() is implemented with std::filesystem::remove_all(). When a
read-only directory has a child, libc++ before LLVM 23 drops the
child's EACCES and reports the ENOTEMPTY it then gets for the parent
instead. The test pinned that behavior to macOS, but it depends on the
C++ standard library rather than on the OS: a Linux build against
libc++ fails the test when run as non-root, and macOS will start
reporting EACCES once it ships the fixed libc++. Accept either code
for that case on all POSIX platforms.
Refs: https://github.com/llvm/llvm-project/pull/197104
Refs: https://github.com/nodejs/node/pull/57103
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66065
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Zero-length FFI memory operations accept a null pointer, but
ToArrayBuffer() and ExportBytes() call memcpy() unconditionally.
Passing a null pointer to memcpy() is undefined behavior even when
the size is zero.
Skip the copy when the length is zero, matching what Buffer::Copy()
already does for the same case.
An isolated reproduction compiled with -fsanitize=undefined reports
"null pointer passed as argument 1, which is declared to never be
null". The added test covers the reachable zero-length paths, but it
passes without the fix: libc does not fault on memcpy(NULL, NULL, 0),
and --enable-ubsan does not set -fno-sanitize-recover, so UBSan
reports the call without failing the process.
Signed-off-by: Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66200
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Use isolated directories for the NODE_OPTIONS watch paths to avoid
recursively watching the repository's source and test trees. Allow a
platform-scaled 10 seconds for startup and restarts.
Remove the flaky markers for test-watch-mode and
test-watch-mode-inspect. The inspector restart race was already fixed
in f2aaf63846.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66232
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
`FreeEnvironment()` forbids JavaScript on the whole isolate with a
`DisallowJavascriptExecutionScope` and then spins the event loop in
`Environment::CleanupHandles()` until its handles are closed. When the
loop and isolate are shared with other Environments, as they are for an
embedder hosting several Environments on one thread, those loop turns
also run the other Environments' timers and I/O callbacks, and every
one of them failed with an "illegal access" exception thrown into
unrelated code.
While an Environment is closing its handles, let `InternalCallbackScope`
re-allow JavaScript for callbacks of Environments that can still call
into JS. The Environment being freed stays blocked: its callbacks fail
the `can_call_into_js()` check before that point, and anything that
bypasses `InternalCallbackScope` (V8 foreground tasks, raw addon
callbacks) still runs under the disallow scope.
Refs: https://github.com/nodejs/node/pull/33874
Refs: https://github.com/nodejs/node/pull/65819
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65977
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
--vfs-mount mounted a source without running it, and shared one ordered
list of sources with --vfs-load, so neither option could say which entry
it had contributed: the entry point was recovered from the position of
--vfs-load among the mounts, in a list NODE_OPTIONS could prepend to.
Nothing needs more than one mount from the command line: a program that
wants more can mount them itself through node:vfs, where it also gets
the instance.
Remove --vfs-mount, leaving --vfs-load with the single source it mounts
and runs, and reserve layer 0 for that source, numbering the file
systems a program mounts itself from 1. The source is then at the same
mount point in every thread, whatever else that thread mounts -
including a thread where a --require preload mounted a file system of
its own first - so a path into it stays valid in a worker.
A worker still does not run that entry point: it inherits the source but
not the decision to load from it. A worker created with its own execArgv
inherits neither, so the documentation now says that such a worker must
be given --experimental-vfs and --vfs-load again to run a script from
the mount, and that --experimental-vfs is also what makes node:vfs
available to the worker's own code.
ERR_VFS_INVALID_TARGET now names --vfs-load as the source's origin, and
the startup test moves to test-vfs-load.js, with the cases that covered
mounting without loading removed and cases for the reserved mount point
added.
Signed-off-by: Philipp Dunkel <pip@pipobscure.com>
PR-URL: https://github.com/nodejs/node/pull/66162
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
`SetIsolateMiscHandlers()` always installs Node.js's
`WebAssembly.compileStreaming()` implementation, which is backed by the
Environment's fetch-based handler. An embedder that provides its own
streaming callback (for example one wired to its own network stack) has
to re-install it after every `SetIsolateUpForNode()` or `NewIsolate()`
call. Add `SHOULD_NOT_SET_WASM_STREAMING_CALLBACK` next to the existing
`SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK` and
`SHOULD_NOT_SET_PREPARE_STACK_TRACE_CALLBACK` flags so it can opt out
the same way.
Refs: https://github.com/nodejs/node/pull/36447
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65690
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Refresh conditional algorithm registration on FIPS changes and use the
current state for parameter restrictions.
Use per-algorithm availability checks in normalization and native named
key generation. Remove getPqcKeyTypes().
Enable supports() tests under FIPS and cover state transitions in warmed
workers.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66160
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
ZipProvider threw ERR_METHOD_NOT_IMPLEMENTED for readdir() with
`{ recursive: true }`, although an archive already stores every member
under its full path, so a recursive listing is the same scan of the
entry names as a flat one, keeping the whole path below the directory
instead of only its first segment.
List every member below the directory, and every directory their paths
pass through, whether the archive holds an entry for it or only implies
it. Names are relative to the listed directory and joined with `/`, as
MemoryProvider returns them, so VirtualFileSystem reports the right
parentPath for each Dirent. A name that is both a member and a
directory is listed once, as a directory, as a flat listing already
did.
The entries are now collected in a map rather than looked up in an
array, so listing a directory no longer takes time quadratic in the
number of its children.
Signed-off-by: Philipp Dunkel <pip@pipobscure.com>
PR-URL: https://github.com/nodejs/node/pull/66127
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>