Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maxPayload crash: "this.onerror is not a function" in Receiver #680

Closed
rkaw92 opened this issue Feb 13, 2016 · 7 comments
Closed

maxPayload crash: "this.onerror is not a function" in Receiver #680

rkaw92 opened this issue Feb 13, 2016 · 7 comments

Comments

@rkaw92
Copy link

rkaw92 commented Feb 13, 2016

The server code below can easily be crashed by sending a message that is over the size limit of 100 bytes (on master):

var ws = require('ws');

var websocketServer = new ws.Server({
    port: 7717,
    disableHixie: true,
    clientTracking: false,
    perMessageDeflate: false,
    maxPayload: 100
});

websocketServer.on('connection', function(socket) {
    setInterval(function() {
        socket.send('some notification');
    }, 1000);

    socket.on('error', function() {});
});

The output:

/home/thewanderer/Devel/Node/WebSocket/bugs/maxPayload/node_modules/ws/lib/Receiver.js:331
  this.onerror(reason, protocolErrorCode);
       ^

TypeError: this.onerror is not a function
    at Receiver.error (/home/thewanderer/Devel/Node/WebSocket/bugs/maxPayload/node_modules/ws/lib/Receiver.js:331:8)
    at Receiver.<anonymous> (/home/thewanderer/Devel/Node/WebSocket/bugs/maxPayload/node_modules/ws/lib/Receiver.js:483:18)
    at Receiver.add (/home/thewanderer/Devel/Node/WebSocket/bugs/maxPayload/node_modules/ws/lib/Receiver.js:102:24)
    at Socket.realHandler (/home/thewanderer/Devel/Node/WebSocket/bugs/maxPayload/node_modules/ws/lib/WebSocket.js:801:20)
    at emitOne (events.js:90:13)
    at Socket.emit (events.js:182:7)
    at readableAddChunk (_stream_readable.js:147:16)
    at Socket.Readable.push (_stream_readable.js:111:10)
    at TCP.onread (net.js:525:20)

Specifically, I am using a very talkative test client, which keeps sending a 100KB-long "lorem ipsum" as fast as possible.

My guess is that lib/Receiver.js:122 is the part that deletes the function.

@LordMajestros
Copy link
Contributor

@rkaw92 the socket is closed (line 849 in https://github.com/websockets/ws/blob/master/lib/WebSocket.js) after receiving a payload that exceeds the maxPayload (the assumption is a rogue client attempting a DOS) so it should be invalid after that. My guess is there is a race condition i.e. it receives another message before the cleanup is complete but after deleting the function.
What happens if you add a delay to your client?
I will see if I can create a PR with a fix.

@rkaw92
Copy link
Author

rkaw92 commented Feb 13, 2016

It appears that even a single message can crash the server: gist.
For reference, the original client code is here.

No more messages are required. Turning off the maxPayload option (passing zero or undefined) makes the crash go away.

@LordMajestros
Copy link
Contributor

Doing a PR right now to fix

@LordMajestros
Copy link
Contributor

@rkaw92 could you please test this and confirm if the issue is resolved? #681

@LordMajestros
Copy link
Contributor

@rkaw92 you may need to catch the 'not opened' error in thrown in lib/Websocket.js:218:5 to prevent a crash but this crash is expected behaviour.
My modification of your server code:

var ws = require('ws');

var websocketServer = new ws.Server({
    port: 7717,
    disableHixie: true,
    clientTracking: false,
    perMessageDeflate: false,
    maxPayload: 100
});

websocketServer.on('connection', function(socket) {
    setInterval(function() {
        try{
            socket.send('some notification');
        }
        catch(exception){
        }
    }, 1000);

    socket.on('error', function(error) {
        console.log("An error occured",error);
    });
});

@rkaw92
Copy link
Author

rkaw92 commented Feb 15, 2016

Indeed, the fix does work. Apparently, the try {} catch block is also required around the server's .send() - otherwise an "Error: not opened" is thrown.

@LordMajestros
Copy link
Contributor

Thanks @rkaw92 cc @3rd-Eden

@rkaw92 rkaw92 closed this as completed Feb 19, 2016
3rd-Eden added a commit that referenced this issue Mar 29, 2016
th37rose added a commit to th37rose/websocket_server that referenced this issue May 24, 2022
th37rose added a commit to th37rose/websocket_server that referenced this issue May 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants