mirror of
https://github.com/socketio/socket.io.git
synced 2026-04-30 03:00:39 -04:00
Backported from main: b25738c416
When a packet contains binary elements, the built-in parser does not modify them and simply sends them in their own WebSocket frame.
Example: `socket.emit("some event", Buffer.of(1,2,3))`
is encoded and transferred as:
- 1st frame: 51-["some event",{"_placeholder":true,"num":0}]
- 2nd frame: <buffer 01 02 03>
where:
- `5` is the type of the packet (binary message)
- `1` is the number of binary attachments
- `-` is the separator
- `["some event",{"_placeholder":true,"num":0}]` is the payload (including the placeholder)
On the receiving end, the parser reads the number of attachments and buffers them until they are all received.
Before this change, the built-in parser accepted any number of binary attachments, which could be exploited to make the server run out of memory.
The number of attachments is now limited to 10, which should be sufficient for most use cases.
The limit can be increased with a custom `parser`:
```js
import { Encoder, Decoder } from "socket.io-parser";
const io = new Server({
parser: {
Encoder,
Decoder: class extends Decoder {
constructor() {
super({
maxAttachments: 20
});
}
}
}
});
```
127 lines
3.0 KiB
JavaScript
127 lines
3.0 KiB
JavaScript
var parser = require('../index.js');
|
|
var expect = require('expect.js');
|
|
var helpers = require('./helpers.js');
|
|
|
|
describe('parser', function(){
|
|
|
|
it('exposes types', function(){
|
|
expect(parser.CONNECT).to.be.a('number');
|
|
expect(parser.DISCONNECT).to.be.a('number');
|
|
expect(parser.EVENT).to.be.a('number');
|
|
expect(parser.ACK).to.be.a('number');
|
|
expect(parser.ERROR).to.be.a('number');
|
|
expect(parser.BINARY_EVENT).to.be.a('number');
|
|
expect(parser.BINARY_ACK).to.be.a('number');
|
|
});
|
|
|
|
it('encodes connection', function(){
|
|
helpers.test({
|
|
type: parser.CONNECT,
|
|
nsp: '/woot'
|
|
});
|
|
});
|
|
|
|
it('encodes disconnection', function(){
|
|
helpers.test({
|
|
type: parser.DISCONNECT,
|
|
nsp: '/woot'
|
|
});
|
|
});
|
|
|
|
it('encodes an event', function(){
|
|
helpers.test({
|
|
type: parser.EVENT,
|
|
data: ['a', 1, {}],
|
|
nsp: '/'
|
|
});
|
|
helpers.test({
|
|
type: parser.EVENT,
|
|
data: ['a', 1, {}],
|
|
id: 1,
|
|
nsp: '/test'
|
|
});
|
|
});
|
|
|
|
it('encodes an ack', function(){
|
|
helpers.test({
|
|
type: parser.ACK,
|
|
data: ['a', 1, {}],
|
|
id: 123,
|
|
nsp: '/'
|
|
});
|
|
});
|
|
|
|
it('encodes an error', function(){
|
|
helpers.test({
|
|
type: parser.ERROR,
|
|
data: 'Unauthorized',
|
|
nsp: '/'
|
|
});
|
|
});
|
|
|
|
it('properly handles circular objects', function() {
|
|
var a = {};
|
|
a.b = a;
|
|
|
|
var data = {
|
|
type: parser.EVENT,
|
|
data: a,
|
|
id: 1,
|
|
nsp: '/'
|
|
}
|
|
|
|
var encoder = new parser.Encoder();
|
|
|
|
encoder.encode(data, function(encodedPackets) {
|
|
expect(encodedPackets[0]).to.be('4"encode error"');
|
|
});
|
|
});
|
|
|
|
it('decodes a bad binary packet', function(){
|
|
try {
|
|
var decoder = new parser.Decoder();
|
|
decoder.add('5');
|
|
} catch(e){
|
|
expect(e.message).to.match(/Illegal/);
|
|
}
|
|
});
|
|
|
|
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"]');
|
|
|
|
function isInvalidAttachmentCount (str) {
|
|
expect(() => new parser.Decoder().add(str)).to.throwException(
|
|
/^Illegal attachments$/,
|
|
);
|
|
}
|
|
|
|
isInvalidAttachmentCount("5");
|
|
isInvalidAttachmentCount("51");
|
|
isInvalidAttachmentCount("5a-");
|
|
isInvalidAttachmentCount("51.23-");
|
|
});
|
|
|
|
it("throws an error when receiving too many attachments", () => {
|
|
const decoder = new parser.Decoder({ maxAttachments: 2 });
|
|
|
|
expect(() => {
|
|
decoder.add(
|
|
'53-["hello",{"_placeholder":true,"num":0},{"_placeholder":true,"num":1},{"_placeholder":true,"num":2}]',
|
|
);
|
|
}).to.throwException(/^too many attachments$/);
|
|
});
|
|
});
|