Skip to content

Commit

Permalink
fallback to Buffer.isUtf8 on platforms without icu (#3006)
Browse files Browse the repository at this point in the history
  • Loading branch information
KhafraDev committed Apr 4, 2024
1 parent 744c9b7 commit cae5625
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
5 changes: 2 additions & 3 deletions lib/web/websocket/receiver.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { Writable } = require('node:stream')
const { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = require('./constants')
const { kReadyState, kSentClose, kResponse, kReceivedClose } = require('./symbols')
const { channels } = require('../../core/diagnostics')
const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = require('./util')
const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived, utf8Decode } = require('./util')
const { WebsocketFrameSend } = require('./frame')

// This code was influenced by ws released under the MIT license.
Expand Down Expand Up @@ -314,8 +314,7 @@ class ByteParser extends Writable {
}

try {
// TODO: optimize this
reason = new TextDecoder('utf-8', { fatal: true }).decode(reason)
reason = utf8Decode(reason)
} catch {
return null
}
Expand Down
33 changes: 31 additions & 2 deletions lib/web/websocket/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = require('./symbols')
const { states, opcodes } = require('./constants')
const { MessageEvent, ErrorEvent } = require('./events')
const { isUtf8 } = require('node:buffer')

/* globals Blob */

Expand Down Expand Up @@ -87,7 +88,7 @@ function websocketMessageReceived (ws, type, data) {
// -> type indicates that the data is Text
// a new DOMString containing data
try {
dataForEvent = new TextDecoder('utf-8', { fatal: true }).decode(data)
dataForEvent = utf8Decode(data)
} catch {
failWebsocketConnection(ws, 'Received invalid UTF-8 in text frame.')
return
Expand Down Expand Up @@ -200,6 +201,33 @@ function failWebsocketConnection (ws, reason) {
}
}

// 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

/**
* Converts a Buffer to utf-8, even on platforms without icu.
* @param {Buffer} buffer
*/
function utf8Decode (buffer) {
if (hasIntl) {
return fatalDecoder.decode(buffer)
} else {
if (!isUtf8?.(buffer)) {
// TODO: remove once node 18 or < node v18.14.0 is dropped
if (!isUtf8) {
process.emitWarning('ICU is not supported and no fallback exists. Please upgrade to at least Node v18.14.0.', {
code: 'UNDICI-WS-NO-ICU'
})
}

throw new TypeError('Invalid utf-8 received.')
}

return buffer.toString('utf-8')
}
}

module.exports = {
isConnecting,
isEstablished,
Expand All @@ -209,5 +237,6 @@ module.exports = {
isValidSubprotocol,
isValidStatusCode,
failWebsocketConnection,
websocketMessageReceived
websocketMessageReceived,
utf8Decode
}

0 comments on commit cae5625

Please sign in to comment.