mirror of
https://github.com/socketio/socket.io.git
synced 2026-04-30 03:00:39 -04:00
Compare commits
15 Commits
socket.io-
...
socket.io-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
082b68394f | ||
|
|
3263ce0f13 | ||
|
|
719f9ebab0 | ||
|
|
d256cf1efc | ||
|
|
060339a206 | ||
|
|
2dc3c92622 | ||
|
|
4b3c191bc4 | ||
|
|
04d23cecaf | ||
|
|
6a59237ed0 | ||
|
|
a8130ce3a9 | ||
|
|
dcb942d24d | ||
|
|
a5d04354e6 | ||
|
|
652402a856 | ||
|
|
9b3572ea23 | ||
|
|
de1fd36dc9 |
35
.github/workflows/ci.yml
vendored
Normal file
35
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'socket.io-parser/3.4.x'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-node:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version:
|
||||
- 16
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
31
.github/workflows/publish.yml
vendored
Normal file
31
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# reference: https://docs.npmjs.com/trusted-publishers#for-github-actions
|
||||
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'socket.io-parser@*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Use Node.js 24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Publish package
|
||||
run: npm publish --tag v2-latest
|
||||
22
.travis.yml
22
.travis.yml
@@ -1,22 +0,0 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '8'
|
||||
- '10'
|
||||
git:
|
||||
depth: 1
|
||||
matrix:
|
||||
include:
|
||||
- node_js: node
|
||||
env: BROWSERS=1
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
env:
|
||||
global:
|
||||
- secure: >-
|
||||
Ea4P/R9UlWzDlHSP5ynmLiD/YgLjecIvCviOcRTle9mV3P1j2k94Ay1LVu1Jw4whlNmWLq2Z/p8M63L92ODPMlarPsuME8HlP4zGr41whFhRbFdda4k3zrHfUhZBlnhY1MVWXTtVm/l7DOzpBrNh+wKecxZB3yyyEaA+PSG3qcQ=
|
||||
- secure: >-
|
||||
JmPf38qx5Rb6K+WYOMwb5YmESkDmVJ6tgggiJIuyRfHsgQVOO7XBwZuspIKGTSFolUIMaqwQe79Kd+Ehs2ZZ/0lUyF2/6xW3FqFnASUusYJcZdfRjypmBFWs6BRdtEORM8HL0dgBx4O4u/e4ZvtygumbPahjQbMDaqN+MvlpjD0=
|
||||
- secure: >-
|
||||
c3pnLhy3VDJqMl16ABA+8vt3I623aNa2wkLceLXb2V1Dc6eiZeulDH2ekwmdVo/r2WwGIKP3Y6B0mq/xP4W0hg4uT+xWh0AmFHclVyM/yp/AqfXrDUv17Vm0vB7OIgp332OiAlK6Dr13YDbWW8iZxmID41O2+2qohLGPn5JMncg=
|
||||
33
CHANGELOG.md
Normal file
33
CHANGELOG.md
Normal file
@@ -0,0 +1,33 @@
|
||||
## [3.4.4](https://github.com/socketio/socket.io-parser/compare/3.4.3...3.4.4) (2026-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add a limit to the number of binary attachments ([719f9eb](https://github.com/socketio/socket.io/commit/719f9ebab0772ffb882bd614b387e585c1aa75d4))
|
||||
|
||||
|
||||
|
||||
## [3.4.3](https://github.com/socketio/socket.io-parser/compare/3.4.2...3.4.3) (2023-05-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* check the format of the event name ([2dc3c92](https://github.com/socketio/socket.io-parser/commit/2dc3c92622dad113b8676be06f23b1ed46b02ced))
|
||||
|
||||
|
||||
|
||||
## [3.4.2](https://github.com/socketio/socket.io-parser/compare/3.4.1...3.4.2) (2022-11-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* check the format of the index of each attachment ([04d23ce](https://github.com/socketio/socket.io-parser/commit/04d23cecafe1b859fb03e0cbf6ba3b74dff56d14))
|
||||
|
||||
|
||||
|
||||
## [3.4.1](https://github.com/socketio/socket.io-parser/compare/3.4.0...3.4.1) (2020-05-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* prevent DoS (OOM) via massive packets ([#95](https://github.com/socketio/socket.io-parser/issues/95)) ([dcb942d](https://github.com/socketio/socket.io-parser/commit/dcb942d24db97162ad16a67c2a0cf30875342d55))
|
||||
@@ -4,7 +4,7 @@
|
||||
[](http://travis-ci.org/socketio/socket.io-parser)
|
||||
[](http://badge.fury.io/js/socket.io-parser)
|
||||
|
||||
A socket.io encoder and decoder written in JavaScript complying with version `3`
|
||||
A socket.io encoder and decoder written in JavaScript complying with version `4`
|
||||
of [socket.io-protocol](https://github.com/socketio/socket.io-protocol).
|
||||
Used by [socket.io](https://github.com/automattic/socket.io) and
|
||||
[socket.io-client](https://github.com/automattic/socket.io-client).
|
||||
|
||||
12
binary.js
12
binary.js
@@ -70,8 +70,16 @@ exports.reconstructPacket = function(packet, buffers) {
|
||||
function _reconstructPacket(data, buffers) {
|
||||
if (!data) return data;
|
||||
|
||||
if (data && data._placeholder) {
|
||||
return buffers[data.num]; // appropriate buffer (should be natural order anyway)
|
||||
if (data && data._placeholder === true) {
|
||||
var isIndexValid =
|
||||
typeof data.num === "number" &&
|
||||
data.num >= 0 &&
|
||||
data.num < buffers.length;
|
||||
if (isIndexValid) {
|
||||
return buffers[data.num]; // appropriate buffer (should be natural order anyway)
|
||||
} else {
|
||||
throw new Error("illegal attachments");
|
||||
}
|
||||
} else if (isArray(data)) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
data[i] = _reconstructPacket(data[i], buffers);
|
||||
|
||||
74
index.js
74
index.js
@@ -218,8 +218,12 @@ function encodeAsBinary(obj, callback) {
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Decoder() {
|
||||
function Decoder(opts) {
|
||||
this.reconstructor = null;
|
||||
opts = opts || {};
|
||||
this.opts = {
|
||||
maxAttachments: opts.maxAttachments || 10,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +243,10 @@ Emitter(Decoder.prototype);
|
||||
Decoder.prototype.add = function(obj) {
|
||||
var packet;
|
||||
if (typeof obj === 'string') {
|
||||
packet = decodeString(obj);
|
||||
if (this.reconstructor) {
|
||||
throw new Error("got plaintext data when reconstructing a packet");
|
||||
}
|
||||
packet = decodeString(obj, this.opts.maxAttachments);
|
||||
if (exports.BINARY_EVENT === packet.type || exports.BINARY_ACK === packet.type) { // binary packet's json
|
||||
this.reconstructor = new BinaryReconstructor(packet);
|
||||
|
||||
@@ -269,11 +276,12 @@ Decoder.prototype.add = function(obj) {
|
||||
* Decode a packet String (JSON data)
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {Number} maxAttachments - the maximum number of binary attachments
|
||||
* @return {Object} packet
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function decodeString(str) {
|
||||
function decodeString(str, maxAttachments) {
|
||||
var i = 0;
|
||||
// look up type
|
||||
var p = {
|
||||
@@ -286,26 +294,30 @@ function decodeString(str) {
|
||||
|
||||
// look up attachments if type binary
|
||||
if (exports.BINARY_EVENT === p.type || exports.BINARY_ACK === p.type) {
|
||||
var buf = '';
|
||||
while (str.charAt(++i) !== '-') {
|
||||
buf += str.charAt(i);
|
||||
if (i == str.length) break;
|
||||
}
|
||||
var start = i + 1;
|
||||
while (str.charAt(++i) !== '-' && i != str.length) {}
|
||||
var buf = str.substring(start, i);
|
||||
if (buf != Number(buf) || str.charAt(i) !== '-') {
|
||||
throw new Error('Illegal attachments');
|
||||
}
|
||||
p.attachments = Number(buf);
|
||||
var n = Number(buf);
|
||||
if (!isInteger(n) || n < 0) {
|
||||
throw new Error("Illegal attachments");
|
||||
} else if (n > maxAttachments) {
|
||||
throw new Error("too many attachments");
|
||||
}
|
||||
p.attachments = n;
|
||||
}
|
||||
|
||||
// look up namespace (if any)
|
||||
if ('/' === str.charAt(i + 1)) {
|
||||
p.nsp = '';
|
||||
var start = i + 1;
|
||||
while (++i) {
|
||||
var c = str.charAt(i);
|
||||
if (',' === c) break;
|
||||
p.nsp += c;
|
||||
if (i === str.length) break;
|
||||
}
|
||||
p.nsp = str.substring(start, i);
|
||||
} else {
|
||||
p.nsp = '/';
|
||||
}
|
||||
@@ -313,27 +325,25 @@ function decodeString(str) {
|
||||
// look up id
|
||||
var next = str.charAt(i + 1);
|
||||
if ('' !== next && Number(next) == next) {
|
||||
p.id = '';
|
||||
var start = i + 1;
|
||||
while (++i) {
|
||||
var c = str.charAt(i);
|
||||
if (null == c || Number(c) != c) {
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
p.id += str.charAt(i);
|
||||
if (i === str.length) break;
|
||||
}
|
||||
p.id = Number(p.id);
|
||||
p.id = Number(str.substring(start, i + 1));
|
||||
}
|
||||
|
||||
// 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 +359,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
|
||||
*
|
||||
@@ -413,3 +443,13 @@ function error(msg) {
|
||||
data: 'parser error: ' + msg
|
||||
};
|
||||
}
|
||||
|
||||
var isInteger =
|
||||
Number.isInteger ||
|
||||
function (value) {
|
||||
return (
|
||||
typeof value === "number" &&
|
||||
isFinite(value) &&
|
||||
Math.floor(value) === value
|
||||
);
|
||||
};
|
||||
|
||||
8257
package-lock.json
generated
Normal file
8257
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "socket.io-parser",
|
||||
"version": "3.3.0",
|
||||
"version": "3.4.4",
|
||||
"description": "socket.io protocol parser",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Automattic/socket.io-parser.git"
|
||||
"url": "git+https://github.com/socketio/socket.io.git"
|
||||
},
|
||||
"files": [
|
||||
"binary.js",
|
||||
@@ -12,11 +12,14 @@
|
||||
"is-buffer.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"debug": "~3.1.0",
|
||||
"debug": "~4.1.0",
|
||||
"component-emitter": "1.2.1",
|
||||
"isarray": "2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "~7.9.6",
|
||||
"@babel/preset-env": "~7.9.6",
|
||||
"babelify": "~10.0.0",
|
||||
"benchmark": "2.1.2",
|
||||
"expect.js": "0.3.1",
|
||||
"mocha": "3.2.0",
|
||||
@@ -27,5 +30,8 @@
|
||||
"scripts": {
|
||||
"test": "make test"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: '/'
|
||||
};
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
var parser = require('../index.js');
|
||||
var expect = require('expect.js');
|
||||
var helpers = require('./helpers.js');
|
||||
var encode = parser.encode;
|
||||
var decode = parser.decode;
|
||||
var Decoder = parser.Decoder;
|
||||
|
||||
describe('parser', function() {
|
||||
it('encodes a Buffer', function() {
|
||||
@@ -14,6 +13,15 @@ describe('parser', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it("encodes a nested Buffer", function() {
|
||||
helpers.test_bin({
|
||||
type: parser.BINARY_EVENT,
|
||||
data: ["a", { b: ["c", Buffer.from("abc", "utf8")] }],
|
||||
id: 23,
|
||||
nsp: "/cool",
|
||||
});
|
||||
});
|
||||
|
||||
it('encodes a binary ack with Buffer', function() {
|
||||
helpers.test_bin({
|
||||
type: parser.BINARY_ACK,
|
||||
@@ -22,4 +30,39 @@ describe('parser', function() {
|
||||
nsp: '/back'
|
||||
})
|
||||
});
|
||||
|
||||
it("throws an error when adding an attachment with an invalid 'num' attribute (string)", function() {
|
||||
var decoder = new Decoder();
|
||||
|
||||
expect(function() {
|
||||
decoder.add('51-["hello",{"_placeholder":true,"num":"splice"}]');
|
||||
decoder.add(Buffer.from("world"));
|
||||
}).to.throwException(/^illegal attachments$/);
|
||||
});
|
||||
|
||||
it("throws an error when adding an attachment with an invalid 'num' attribute (out-of-bound)", function() {
|
||||
var decoder = new Decoder();
|
||||
|
||||
expect(function() {
|
||||
decoder.add('51-["hello",{"_placeholder":true,"num":1}]');
|
||||
decoder.add(Buffer.from("world"));
|
||||
}).to.throwException(/^illegal attachments$/);
|
||||
});
|
||||
|
||||
it("throws an error when adding an attachment without header", function() {
|
||||
var decoder = new Decoder();
|
||||
|
||||
expect(function() {
|
||||
decoder.add(Buffer.from("world"));
|
||||
}).to.throwException(/^got binary data when not reconstructing a packet$/);
|
||||
});
|
||||
|
||||
it("throws an error when decoding a binary event without attachments", function() {
|
||||
var decoder = new Decoder();
|
||||
|
||||
expect(function() {
|
||||
decoder.add('51-["hello",{"_placeholder":true,"num":0}]');
|
||||
decoder.add('2["hello"]');
|
||||
}).to.throwException(/^got plaintext data when reconstructing a packet$/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -86,12 +86,41 @@ 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"]');
|
||||
|
||||
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$/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,6 +23,16 @@ if (process.env.CI === 'true') {
|
||||
type: 'ngrok',
|
||||
bind_tls: true
|
||||
};
|
||||
zuulConfig.browserify = [
|
||||
{
|
||||
transform: {
|
||||
name: "babelify",
|
||||
presets: ["@babel/preset-env"],
|
||||
global: true,
|
||||
only: [ /\/node_modules\/debug\// ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
var isPullRequest = process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false';
|
||||
|
||||
Reference in New Issue
Block a user