From 2dc3c92622dad113b8676be06f23b1ed46b02ced Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Mon, 22 May 2023 09:56:28 +0200 Subject: [PATCH] fix: check the format of the event name A packet like '2[{"toString":"foo"}]' was decoded as: { type: EVENT, data: [ { "toString": "foo" } ] } Which would then throw an error when passed to the EventEmitter class: > TypeError: Cannot convert object to primitive value > at Socket.emit (node:events:507:25) > at .../node_modules/socket.io/lib/socket.js:531:14 History of the isPayloadValid() method: - added in [78f9fc2](78f9fc2) (v4.0.1, socket.io@3.0.0) - updated in [1c220dd](1c220dd) (v4.0.4, socket.io@3.1.0) Backported from https://github.com/socketio/socket.io-parser/commit/3b78117bf6ba7e99d7a5cfc1ba54d0477554a7f3 --- index.js | 25 ++++++++++++++++++++++--- test/arraybuffer.js | 2 +- test/parser.js | 22 +++++++++++++++------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 245a800..50ff90e 100644 --- a/index.js +++ b/index.js @@ -329,11 +329,10 @@ function decodeString(str) { // look up json data if (str.charAt(++i)) { var payload = tryParse(str.substr(i)); - var isPayloadValid = payload !== false && (p.type === exports.ERROR || isArray(payload)); - if (isPayloadValid) { + if (isPayloadValid(p.type, payload)) { p.data = payload; } else { - return error('invalid payload'); + throw new Error("invalid payload"); } } @@ -349,6 +348,26 @@ function tryParse(str) { } } +function isPayloadValid(type, payload) { + switch (type) { + case 0: // CONNECT + return typeof payload === "object"; + case 1: // DISCONNECT + return payload === undefined; + case 4: // ERROR + return typeof payload === "string" || typeof payload === "object"; + case 2: // EVENT + case 5: // BINARY_EVENT + return ( + isArray(payload) && + (typeof payload[0] === "string" || typeof payload[0] === "number") + ); + case 3: // ACK + case 6: // BINARY_ACK + return isArray(payload); + } +} + /** * Deallocates a parser's resources * diff --git a/test/arraybuffer.js b/test/arraybuffer.js index c8295f1..f2948a5 100644 --- a/test/arraybuffer.js +++ b/test/arraybuffer.js @@ -50,7 +50,7 @@ describe('parser', function() { it('cleans itself up on close', function() { var packet = { type: parser.BINARY_EVENT, - data: [new ArrayBuffer(2), new ArrayBuffer(3)], + data: ["foo", new ArrayBuffer(2), new ArrayBuffer(3)], id: 0, nsp: '/' }; diff --git a/test/parser.js b/test/parser.js index 652aa7f..7d560bf 100644 --- a/test/parser.js +++ b/test/parser.js @@ -86,12 +86,20 @@ describe('parser', function(){ } }); - it('returns an error packet on parsing error', function(done){ - var decoder = new parser.Decoder(); - decoder.on('decoded', function(packet) { - expect(packet).to.eql({ type: 4, data: 'parser error: invalid payload' }); - done(); - }); - decoder.add('442["some","data"'); + it('returns an error packet on parsing error', function(){ + function isInvalidPayload (str) { + expect(function () { + new parser.Decoder().add(str) + }).to.throwException(/^invalid payload$/); + } + + isInvalidPayload('442["some","data"'); + isInvalidPayload('0/admin,"invalid"'); + isInvalidPayload("1/admin,{}"); + isInvalidPayload('2/admin,"invalid'); + isInvalidPayload("2/admin,{}"); + isInvalidPayload('2[{"toString":"foo"}]'); + isInvalidPayload('2[true,"foo"]'); + isInvalidPayload('2[null,"bar"]'); }); });