Skip to content

Uncatchable error for close message of 123 bytes because of encoding issues #1868

@viyaha

Description

@viyaha
  • I've searched for any related issues and avoided creating a duplicate issue.

Description

If the other side has a problem and closes the websocket-connection with an message this message must not be greater than 123 bytes, otherwise an error will be thrown (that is not catchable by the client code, there needs to be an "unhandled exception handler" for those errors.

The issue is, the message itself is exactly 123 bytes long (and shouldn't throw), but the byte-message will be converted to a string before checking the bytelength of the string. If there are encoding issues some � will be inserted in the string, afterwards the bytelength of the string is greater than 123 and the error is thrown.

String-Conversion:

this.emit('conclude', code, buf.toString());

ByteLength-Check:

ws/lib/sender.js

Lines 117 to 121 in 114de9e

const length = Buffer.byteLength(data);
if (length > 123) {
throw new RangeError('The message must not be greater than 123 bytes');
}

Reproducible in:

  • version: 7.4.4
  • Node.js version(s): v14.15.0
  • OS version(s): Windows 10 Pro 19042.867

Steps to reproduce:

Easiest way to check this issue is pure node (without the package):

// we're staying with �, just to make it easier, � => "efbfbd" ===> "efbf" is not valid and node will replace it with �, because of the encoding issues
const firstBuffer = Buffer.from("efbf", "hex");
const secondBuffer = Buffer.from("efbfbd", "hex");
const firstString = firstBuffer.toString();
const secondString = secondBuffer.toString();

console.log(firstBuffer.byteLength); // 2
console.log(secondBuffer.byteLength); // 3
console.log(Buffer.byteLength(firstString)); // 3
console.log(Buffer.byteLength(secondString)); // 3

console.log(firstString === secondString); // true � === �

This happends quite easily, if the "closer" doesn't validate the utf8-correctness of the shortened byte-message. This happens if the message just get cuts after 123 bytes => removes a byte from a character.

Expected result:

Either allow it (check the bytelength of the Buffer before converting it to string) or throw the error in the caller stack => The user needs to be able to handle this.

Actual result:

Uncatchable Error (outside of caller stack).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions