diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js index 9971a131eb..cbc42bff69 100644 --- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js +++ b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js @@ -668,7 +668,15 @@ module.exports = function(RED) { let event; while (event = dequeue(clients[connection_id].msgQueue)) { if (event.msg.payload !== undefined) { - clients[connection_id].client.write(event.msg.payload); + if (typeof event.msg.payload !== 'string' && !Buffer.isBuffer(event.msg.payload) && !(event.msg.payload instanceof Uint8Array)) { + node.error(`TCP Out Invalid payload type: ${typeof event.msg.payload}. Expected Buffer, Uint8Array, or string.`, event.msg); + } else { + try { + clients[connection_id].client.write(event.msg.payload); + } catch (err) { + node.error(err, event.msg); + } + } } event.nodeDone(); } @@ -870,7 +878,15 @@ module.exports = function(RED) { if (clients[connection_id] && clients[connection_id].client) { let event = dequeue(clients[connection_id].msgQueue) if (event.msg.payload !== undefined ) { - clients[connection_id].client.write(event.msg.payload); + if (typeof event.msg.payload !== 'string' && !Buffer.isBuffer(event.msg.payload) && !(event.msg.payload instanceof Uint8Array)) { + node.error(`TCP Out Invalid payload type: ${typeof event.msg.payload}. Expected Buffer, Uint8Array, or string.`, event.msg); + } else { + try { + clients[connection_id].client.write(event.msg.payload); + } catch (err) { + node.error(err, event.msg); + } + } } event.nodeDone(); } diff --git a/test/nodes/core/network/31-tcprequest_spec.js b/test/nodes/core/network/31-tcprequest_spec.js index 154aa41654..c0669d462f 100644 --- a/test/nodes/core/network/31-tcprequest_spec.js +++ b/test/nodes/core/network/31-tcprequest_spec.js @@ -351,5 +351,34 @@ describe('TCP Request Node', function() { topic: 'quux' }, done); }); + + it('should handle payload mutation to number during connection without crashing and log an error', function(done) { + var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"time", splitc: "0", wires:[["n2"]] }, + {id:"n2", type:"helper"}]; + helper.load(tcpinNode, flow, function() { + var n1 = helper.getNode("n1"); + var msg = { payload: Buffer.from("foo") }; + n1.receive(msg); + // Mutate the payload to a number synchronously after enqueue but before connection callback runs + msg.payload = 2; + + setTimeout(function() { + try { + helper.log().called.should.be.true(); + var logEvents = helper.log().args.filter(function (evt) { + return evt[0].type == "tcp request"; + }); + logEvents.should.have.length(1); + var logMsg = logEvents[0][0]; + logMsg.should.have.property('level', helper.log().ERROR); + logMsg.should.have.property('id', 'n1'); + logMsg.msg.should.containEql('Invalid payload type: number'); + done(); + } catch (err) { + done(err); + } + }, 100); + }); + }); }); });