From ef8e1e017bde5083725373e9f100d8e78f72d9d3 Mon Sep 17 00:00:00 2001 From: Khafra Date: Thu, 16 May 2024 10:25:09 -0400 Subject: [PATCH] fixup --- lib/web/websocket/permessage-deflate.js | 17 +++++++++++++++-- lib/web/websocket/util.js | 20 +++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lib/web/websocket/permessage-deflate.js b/lib/web/websocket/permessage-deflate.js index 3918fd436c0..d349863888f 100644 --- a/lib/web/websocket/permessage-deflate.js +++ b/lib/web/websocket/permessage-deflate.js @@ -1,6 +1,7 @@ 'use strict' -const { createInflateRaw } = require('node:zlib') +const { createInflateRaw, Z_DEFAULT_WINDOWBITS } = require('node:zlib') +const { isValidClientWindowBits } = require('./util') const tail = Buffer.from([0x00, 0x00, 0xff, 0xff]) const kBuffer = Symbol('kBuffer') @@ -14,6 +15,7 @@ class PerMessageDeflate { constructor (extensions) { this.#options.clientNoContextTakeover = extensions.has('client_no_context_takeover') + this.#options.clientMaxWindowBits = extensions.get('client_max_window_bits') } decompress (chunk, fin, callback) { @@ -23,7 +25,18 @@ class PerMessageDeflate { // 2. Decompress the resulting data using DEFLATE. if (!this.#inflate) { - this.#inflate = createInflateRaw(/* TODO */) + let windowBits = Z_DEFAULT_WINDOWBITS + + if (this.#options.clientMaxWindowBits) { // empty values default to Z_DEFAULT_WINDOWBITS + if (!isValidClientWindowBits(this.#options.clientMaxWindowBits)) { + callback(new Error('Invalid client_max_window_bits')) + return + } + + windowBits = Number.parseInt(this.#options.clientMaxWindowBits) + } + + this.#inflate = createInflateRaw({ windowBits }) this.#inflate[kBuffer] = [] this.#inflate[kLength] = 0 diff --git a/lib/web/websocket/util.js b/lib/web/websocket/util.js index 844cff2d007..8a2bae5de45 100644 --- a/lib/web/websocket/util.js +++ b/lib/web/websocket/util.js @@ -259,6 +259,23 @@ function parseExtensions (extensions) { return extensionList } +/** + * @see https://www.rfc-editor.org/rfc/rfc7692#section-7.1.2.2 + * @description "client-max-window-bits = 1*DIGIT" + * @param {string} value + */ +function isValidClientWindowBits (value) { + for (let i = 0; i < value.length; i++) { + const byte = value.charCodeAt(i) + + if (byte < 0x30 || byte > 0x39) { + return false + } + } + + return true +} + // https://nodejs.org/api/intl.html#detecting-internationalization-support const hasIntl = typeof process.versions.icu === 'string' const fatalDecoder = hasIntl ? new TextDecoder('utf-8', { fatal: true }) : undefined @@ -291,5 +308,6 @@ module.exports = { isContinuationFrame, isTextBinaryFrame, isValidOpcode, - parseExtensions + parseExtensions, + isValidClientWindowBits }