`bigIntArrayToUnsignedInt` used the signed `<<` operator, so when the
most significant byte of a 4-byte input had its top bit set (e.g.
`[0x80, 0x00, 0x00, 0x01]`) the result was a negative Int32 instead of
the intended unsigned 32-bit value. This caused any RSA `publicExponent`
exactly 4 bytes long with the top bit set to be parsed incorrectly.
Coerce the final value with `>>> 0` and add a unit test.
Assisted-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: DeepView Autofix <276251120+deepview-autofix@users.noreply.github.com>
Co-Authored-By: Nikita Skovoroda <chalkerx@gmail.com>
Signed-off-by: Nikita Skovoroda <chalkerx@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/62839
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Previously, this resulted in an error listener being added but not
cleaned up when the socket was freed back to the agent pool.
This also updates the docs to clarify when req.destroy() kills the
underlying socket - only if it's called during request processing (more
specifically: after onSocketNT, at which point we may have started
reading & writing).
Signed-off-by: Tim Perry <pimterry@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/62872
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This uses the existing WebIDL infrastructure to handle the iteration
over the argument correctly according to the specification.
Note that we can't avoid looping over the input twice: we only know the
value of the 'endings' option after converting the blob parts into an
array.
PR-URL: https://github.com/nodejs/node/pull/62179
Reviewed-By: Mattias Buelens <mattias@buelens.com>
Reviewed-By: Jason Zhang <xzha4350@gmail.com>
When using Duplex.fromWeb() or Writable.fromWeb() with cork()/uncork(),
writes are batched into _writev(). If destroy() is called in the same
microtask, the underlying WritableStream writer gets aborted, causing
SafePromiseAll() to reject with a non-array value (e.g. an AbortError).
The done() callback in _writev() of both fromWeb adapter functions
unconditionally called error.filter(), assuming the value was always an
array. This caused a TypeError that became an unhandled rejection,
crashing the process.
Fix by separating the resolve and reject handlers of SafePromiseAll:
use () => done() on the resolve path (all writes succeeded, no error)
and done on the reject path (error passed directly to callback).
Fixes: https://github.com/nodejs/node/issues/62199
Signed-off-by: sangwook <rewq5991@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/62297
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
When pipelined requests arrive in one TCP segment, llhttp_execute()
parses them all in a single call. If a synchronous 'close' event
handler invokes freeParser() mid-execution, cleanParser() nulls out
parser state while llhttp_execute() is still on the stack, crashing on
the next callback.
Add an is_being_freed_ flag that freeParser() sets via
parser.markFreed() before cleaning state. Proxy::Raw checks the flag
before every callback and returns HPE_USER to abort execution early if
set.
PR-URL: https://github.com/nodejs/node/pull/62095
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
The `path` property on `ClientRequest` was only validated at
construction time. Add a getter/setter so that the same
`INVALID_PATH_REGEX` check runs whenever `req.path` is reassigned,
preventing invalid characters from reaching `_implicitHeader()`.
PR-URL: https://github.com/nodejs/node/pull/62030
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Add validateHeaderName/validateHeaderValue checks for non-link
headers and checkInvalidHeaderChar for the Link value in HTTP/1.1
writeEarlyHints, closing a CRLF injection gap where header names
and values were concatenated into the raw response without
validation.
Also tighten linkValueRegExp to reject CR/LF inside the <...>
URL portion of Link header values.
PR-URL: https://github.com/nodejs/node/pull/61897
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
The WHATWG Streams spec requires that pipeTo's chunk handling must
queue a microtask before calling the write algorithm. This ensures
that enqueue() does not synchronously trigger writes.
Previously, PipeToReadableStreamReadRequest[kChunk] would synchronously
call writableStreamDefaultWriterWrite(), which violated the spec and
caused the WPT test "enqueue() must not synchronously call write
algorithm" to fail.
Fix by wrapping the write operation in queueMicrotask(), which defers
it to the next microtask as required by the spec.
Refs: https://github.com/whatwg/streams/issues/1243
PR-URL: https://github.com/nodejs/node/pull/61800
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Mattias Buelens <mattias@buelens.com>
Add internal fast paths to improve webstreams performance without
changing the public API or breaking spec compliance.
1. ReadableStreamDefaultReader.read() fast path:
When data is already buffered in the controller's queue, return
PromiseResolve() directly without creating a DefaultReadRequest
object. This is spec-compliant because read() returns a Promise,
and resolved promises still run callbacks in the microtask queue.
2. pipeTo() batch read fast path:
When data is buffered, batch reads directly from the controller
queue up to highWaterMark without creating
PipeToReadableStreamReadRequest objects per chunk. Respects
backpressure by checking desiredSize after each write.
Benchmark results:
- pipeTo: ~11% faster (***)
- buffered read(): ~17-20% faster (***)
Co-Authored-By: Malte Ubl <malte@vercel.com>
PR-URL: https://github.com/nodejs/node/pull/61807
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Fixes a race condition in worker thread cwd caching where the counter
is incremented before the directory change completes, allowing workers
to cache stale directory values.
In lib/internal/worker.js, the main thread's process.chdir() wrapper
previously incremented the shared counter before calling the actual
chdir(), creating a race window where workers could read the old
directory but cache it with the new counter value. This caused
subsequent cwd() calls to return incorrect paths until the next chdir().
This fix reorders the operations to change the directory first, then
increment the counter, ensuring workers are only notified after the
directory change completes.
Before fix: 54.28% error rate (311/573 races)
After fix: 0% error rate (0/832 races)
Refs: https://hackerone.com/reports/3407207
Co-authored-by: Giulio Comi
Co-authored-by: Caleb Everett
Co-authored-by: Utku Yildirim
PR-URL: https://github.com/nodejs/node/pull/61664
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
Defer socket.destroy() calls in internalConnect and
internalConnectMultiple to the next tick. This ensures that error
handlers have a chance to be set up before errors are emitted,
particularly important when using http.request with a custom
lookup function that returns synchronously.
Previously, if a synchronous lookup function returned an IP that
triggered an immediate error (e.g., via blockList), the error would
be emitted before the HTTP client had set up its error handler
(which happens via process.nextTick in onSocket). This caused
unhandled 'error' events.
Fixes: https://github.com/nodejs/node/issues/48771
PR-URL: https://github.com/nodejs/node/pull/61658
Refs: https://github.com/nodejs/node/pull/51038
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Jason Zhang <xzha4350@gmail.com>
- Close readline interface after child process exits
Prevents accumulation of event listeners on stderr stream
- Extract watch mode event handler to named function
Allows proper cleanup when watch mode is aborted
These changes prevent unbounded memory growth in long-running
test suites and watch mode sessions.
PR-URL: https://github.com/nodejs/node/pull/60860
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>