Skip to content

Commit e555bf8

Browse files
committed
chore(deps): minor upgrades to dev deps
1 parent 3bad5fc commit e555bf8

5 files changed

Lines changed: 1738 additions & 895 deletions

File tree

dist/main.js

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,6 +2929,24 @@ class SecureProxyConnectionError extends UndiciError {
29292929
[kSecureProxyConnectionError] = true
29302930
}
29312931

2932+
const kMessageSizeExceededError = Symbol.for('undici.error.UND_ERR_WS_MESSAGE_SIZE_EXCEEDED')
2933+
class MessageSizeExceededError extends UndiciError {
2934+
constructor (message) {
2935+
super(message)
2936+
this.name = 'MessageSizeExceededError'
2937+
this.message = message || 'Max decompressed message size exceeded'
2938+
this.code = 'UND_ERR_WS_MESSAGE_SIZE_EXCEEDED'
2939+
}
2940+
2941+
static [Symbol.hasInstance] (instance) {
2942+
return instance && instance[kMessageSizeExceededError] === true
2943+
}
2944+
2945+
get [kMessageSizeExceededError] () {
2946+
return true
2947+
}
2948+
}
2949+
29322950
module.exports = {
29332951
AbortError,
29342952
HTTPParserError,
@@ -2952,7 +2970,8 @@ module.exports = {
29522970
ResponseExceededMaxSizeError,
29532971
RequestRetryError,
29542972
ResponseError,
2955-
SecureProxyConnectionError
2973+
SecureProxyConnectionError,
2974+
MessageSizeExceededError
29562975
}
29572976

29582977

@@ -3029,6 +3048,10 @@ class Request {
30293048
throw new InvalidArgumentError('upgrade must be a string')
30303049
}
30313050

3051+
if (upgrade && !isValidHeaderValue(upgrade)) {
3052+
throw new InvalidArgumentError('invalid upgrade header')
3053+
}
3054+
30323055
if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) {
30333056
throw new InvalidArgumentError('invalid headersTimeout')
30343057
}
@@ -3323,13 +3346,19 @@ function processHeader (request, key, val) {
33233346
val = `${val}`
33243347
}
33253348

3326-
if (request.host === null && headerName === 'host') {
3349+
if (headerName === 'host') {
3350+
if (request.host !== null) {
3351+
throw new InvalidArgumentError('duplicate host header')
3352+
}
33273353
if (typeof val !== 'string') {
33283354
throw new InvalidArgumentError('invalid host header')
33293355
}
33303356
// Consumed by Client
33313357
request.host = val
3332-
} else if (request.contentLength === null && headerName === 'content-length') {
3358+
} else if (headerName === 'content-length') {
3359+
if (request.contentLength !== null) {
3360+
throw new InvalidArgumentError('duplicate content-length header')
3361+
}
33333362
request.contentLength = parseInt(val, 10)
33343363
if (!Number.isFinite(request.contentLength)) {
33353364
throw new InvalidArgumentError('invalid content-length header')
@@ -26046,17 +26075,30 @@ module.exports = {
2604626075

2604726076
const { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __nccwpck_require__(8522)
2604826077
const { isValidClientWindowBits } = __nccwpck_require__(8625)
26078+
const { MessageSizeExceededError } = __nccwpck_require__(8707)
2604926079

2605026080
const tail = Buffer.from([0x00, 0x00, 0xff, 0xff])
2605126081
const kBuffer = Symbol('kBuffer')
2605226082
const kLength = Symbol('kLength')
2605326083

26084+
// Default maximum decompressed message size: 4 MB
26085+
const kDefaultMaxDecompressedSize = 4 * 1024 * 1024
26086+
2605426087
class PerMessageDeflate {
2605526088
/** @type {import('node:zlib').InflateRaw} */
2605626089
#inflate
2605726090

2605826091
#options = {}
2605926092

26093+
/** @type {boolean} */
26094+
#aborted = false
26095+
26096+
/** @type {Function|null} */
26097+
#currentCallback = null
26098+
26099+
/**
26100+
* @param {Map<string, string>} extensions
26101+
*/
2606026102
constructor (extensions) {
2606126103
this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover')
2606226104
this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits')
@@ -26068,6 +26110,11 @@ class PerMessageDeflate {
2606826110
// payload of the message.
2606926111
// 2. Decompress the resulting data using DEFLATE.
2607026112

26113+
if (this.#aborted) {
26114+
callback(new MessageSizeExceededError())
26115+
return
26116+
}
26117+
2607126118
if (!this.#inflate) {
2607226119
let windowBits = Z_DEFAULT_WINDOWBITS
2607326120

@@ -26080,13 +26127,37 @@ class PerMessageDeflate {
2608026127
windowBits = Number.parseInt(this.#options.serverMaxWindowBits)
2608126128
}
2608226129

26083-
this.#inflate = createInflateRaw({ windowBits })
26130+
try {
26131+
this.#inflate = createInflateRaw({ windowBits })
26132+
} catch (err) {
26133+
callback(err)
26134+
return
26135+
}
2608426136
this.#inflate[kBuffer] = []
2608526137
this.#inflate[kLength] = 0
2608626138

2608726139
this.#inflate.on('data', (data) => {
26088-
this.#inflate[kBuffer].push(data)
26140+
if (this.#aborted) {
26141+
return
26142+
}
26143+
2608926144
this.#inflate[kLength] += data.length
26145+
26146+
if (this.#inflate[kLength] > kDefaultMaxDecompressedSize) {
26147+
this.#aborted = true
26148+
this.#inflate.removeAllListeners()
26149+
this.#inflate.destroy()
26150+
this.#inflate = null
26151+
26152+
if (this.#currentCallback) {
26153+
const cb = this.#currentCallback
26154+
this.#currentCallback = null
26155+
cb(new MessageSizeExceededError())
26156+
}
26157+
return
26158+
}
26159+
26160+
this.#inflate[kBuffer].push(data)
2609026161
})
2609126162

2609226163
this.#inflate.on('error', (err) => {
@@ -26095,16 +26166,22 @@ class PerMessageDeflate {
2609526166
})
2609626167
}
2609726168

26169+
this.#currentCallback = callback
2609826170
this.#inflate.write(chunk)
2609926171
if (fin) {
2610026172
this.#inflate.write(tail)
2610126173
}
2610226174

2610326175
this.#inflate.flush(() => {
26176+
if (this.#aborted || !this.#inflate) {
26177+
return
26178+
}
26179+
2610426180
const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength])
2610526181

2610626182
this.#inflate[kBuffer].length = 0
2610726183
this.#inflate[kLength] = 0
26184+
this.#currentCallback = null
2610826185

2610926186
callback(null, full)
2611026187
})
@@ -26158,6 +26235,10 @@ class ByteParser extends Writable {
2615826235
/** @type {Map<string, PerMessageDeflate>} */
2615926236
#extensions
2616026237

26238+
/**
26239+
* @param {import('./websocket').WebSocket} ws
26240+
* @param {Map<string, string>|null} extensions
26241+
*/
2616126242
constructor (ws, extensions) {
2616226243
super()
2616326244

@@ -26300,21 +26381,20 @@ class ByteParser extends Writable {
2630026381

2630126382
const buffer = this.consume(8)
2630226383
const upper = buffer.readUInt32BE(0)
26384+
const lower = buffer.readUInt32BE(4)
2630326385

2630426386
// 2^31 is the maximum bytes an arraybuffer can contain
2630526387
// on 32-bit systems. Although, on 64-bit systems, this is
2630626388
// 2^53-1 bytes.
2630726389
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length
2630826390
// https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275
2630926391
// https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e
26310-
if (upper > 2 ** 31 - 1) {
26392+
if (upper !== 0 || lower > 2 ** 31 - 1) {
2631126393
failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.')
2631226394
return
2631326395
}
2631426396

26315-
const lower = buffer.readUInt32BE(4)
26316-
26317-
this.#info.payloadLength = (upper << 8) + lower
26397+
this.#info.payloadLength = lower
2631826398
this.#state = parserStates.READ_DATA
2631926399
} else if (this.#state === parserStates.READ_DATA) {
2632026400
if (this.#byteOffset < this.#info.payloadLength) {
@@ -26344,7 +26424,7 @@ class ByteParser extends Writable {
2634426424
} else {
2634526425
this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => {
2634626426
if (error) {
26347-
closeWebSocketConnection(this.ws, 1007, error.message, error.message.length)
26427+
failWebsocketConnection(this.ws, error.message)
2634826428
return
2634926429
}
2635026430

@@ -26948,6 +27028,12 @@ function parseExtensions (extensions) {
2694827028
* @param {string} value
2694927029
*/
2695027030
function isValidClientWindowBits (value) {
27031+
// Must have at least one character
27032+
if (value.length === 0) {
27033+
return false
27034+
}
27035+
27036+
// Check all characters are ASCII digits
2695127037
for (let i = 0; i < value.length; i++) {
2695227038
const byte = value.charCodeAt(i)
2695327039

@@ -26956,7 +27042,9 @@ function isValidClientWindowBits (value) {
2695627042
}
2695727043
}
2695827044

26959-
return true
27045+
// Check numeric range: zlib requires windowBits in range 8-15
27046+
const num = Number.parseInt(value, 10)
27047+
return num >= 8 && num <= 15
2696027048
}
2696127049

2696227050
// https://nodejs.org/api/intl.html#detecting-internationalization-support
@@ -27434,7 +27522,7 @@ class WebSocket extends EventTarget {
2743427522
* @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol
2743527523
*/
2743627524
#onConnectionEstablished (response, parsedExtensions) {
27437-
// processResponse is called when the "responses header list has been received and initialized."
27525+
// processResponse is called when the "response's header list has been received and initialized."
2743827526
// once this happens, the connection is open
2743927527
this[kResponse] = response
2744027528

0 commit comments

Comments
 (0)