Skip to content

Commit 2f9138c

Browse files
fix: throw upon invalid packet format
Instead of returning an ERROR packet, the decoder will now throw an error, since it means the other side is sending invalid payloads. The server will then disconnect the client: [1] Fixes #3 [1] https://github.com/socketio/socket.io/blob/2.3.0/lib/client.js#L194-L198
1 parent ee52d11 commit 2f9138c

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

index.js

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ exports.ERROR = 4;
1313
exports.BINARY_EVENT = 5;
1414
exports.BINARY_ACK = 6;
1515

16-
var errorPacket = {
17-
type: exports.ERROR,
18-
data: 'parser error'
16+
var isInteger = Number.isInteger || function (value) {
17+
return typeof value === 'number' &&
18+
isFinite(value) &&
19+
Math.floor(value) === value;
1920
};
2021

22+
var isString = function (value) { return typeof value === 'string'; };
23+
2124
function Encoder () {}
2225

2326
Encoder.prototype.encode = function (packet, callback) {
@@ -28,13 +31,40 @@ function Decoder () {}
2831

2932
Emitter(Decoder.prototype);
3033

34+
function isDataValid (decoded) {
35+
switch (decoded.type) {
36+
case exports.CONNECT:
37+
case exports.DISCONNECT:
38+
return decoded.data === undefined;
39+
case exports.ERROR:
40+
return isString(decoded.data);
41+
default:
42+
return Array.isArray(decoded.data);
43+
}
44+
}
45+
3146
Decoder.prototype.add = function (obj) {
32-
try {
33-
var decoded = JSON.parse(obj);
34-
this.emit('decoded', decoded);
35-
} catch (e) {
36-
this.emit('decoded', errorPacket);
47+
var decoded = JSON.parse(obj);
48+
49+
var isTypeValid = isInteger(decoded.type) && decoded.type >= exports.CONNECT && decoded.type <= exports.BINARY_ACK;
50+
if (!isTypeValid) {
51+
throw new Error('invalid packet type');
52+
}
53+
54+
if (!isString(decoded.nsp)) {
55+
throw new Error('invalid namespace');
3756
}
57+
58+
if (!isDataValid(decoded)) {
59+
throw new Error('invalid payload');
60+
}
61+
62+
var isAckValid = decoded.id === undefined || isInteger(decoded.id);
63+
if (!isAckValid) {
64+
throw new Error('invalid packet id');
65+
}
66+
67+
this.emit('decoded', decoded);
3868
};
3969

4070
Decoder.prototype.destroy = function () {};

test/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,23 @@ describe('parser', () => {
112112
done();
113113
});
114114
});
115+
116+
it('throws an error upon invalid format', () => {
117+
const decoder = new customParser.Decoder();
118+
119+
expect(() => decoder.add('{')).to.throwError(/Unexpected end of JSON input/);
120+
121+
expect(() => decoder.add('{}')).to.throwError(/invalid packet type/);
122+
expect(() => decoder.add('{"type":"a"}')).to.throwError(/invalid packet type/);
123+
expect(() => decoder.add('{"type":7}')).to.throwError(/invalid packet type/);
124+
125+
expect(() => decoder.add('{"type":2}')).to.throwError(/invalid namespace/);
126+
expect(() => decoder.add('{"type":2,"nsp":2}')).to.throwError(/invalid namespace/);
127+
128+
expect(() => decoder.add('{"type":2,"nsp":"/"}')).to.throwError(/invalid payload/);
129+
expect(() => decoder.add('{"type":2,"nsp":"/","data":4}')).to.throwError(/invalid payload/);
130+
expect(() => decoder.add('{"type":4,"nsp":"/","data":[]}')).to.throwError(/invalid payload/);
131+
132+
expect(() => decoder.add('{"type":2,"nsp":"/","data":[],"id":"a"}')).to.throwError(/invalid packet id/);
133+
});
115134
});

0 commit comments

Comments
 (0)