From e991ca82f752837b6571e49325d3e83a0b5b39a1 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Wed, 28 Feb 2018 13:36:08 +0100 Subject: [PATCH] [fix] Properly handle JSON.stringify errors JSON.stringify and hasBin methods may throw when passed a circular object. --- index.js | 31 ++++++++++++++++++++++++++----- test/parser.js | 20 ++++++++++++++++++-- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index f71ff27..16c3f40 100644 --- a/index.js +++ b/index.js @@ -114,6 +114,8 @@ exports.Decoder = Decoder; function Encoder() {} +var ERROR_PACKET = exports.ERROR + '"encode error"'; + /** * Encode a packet as a single string if non-binary, or as a * buffer sequence, depending on packet type. @@ -125,16 +127,22 @@ function Encoder() {} */ Encoder.prototype.encode = function(obj, callback){ - if ((obj.type === exports.EVENT || obj.type === exports.ACK) && hasBin(obj.data)) { - obj.type = obj.type === exports.EVENT ? exports.BINARY_EVENT : exports.BINARY_ACK; + + if (obj.type === exports.EVENT || obj.type === exports.ACK) { + try { + if (hasBin(obj.data)) { + obj.type = obj.type === exports.EVENT ? exports.BINARY_EVENT : exports.BINARY_ACK; + } + } catch (e) { + callback([ERROR_PACKET]); + } } debug('encoding packet %j', obj); if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) { encodeAsBinary(obj, callback); - } - else { + } else { var encoding = encodeAsString(obj); callback([encoding]); } @@ -171,13 +179,26 @@ function encodeAsString(obj) { // json data if (null != obj.data) { - str += JSON.stringify(obj.data); + var payload = tryStringify(obj.data); + if (payload !== false) { + str += payload; + } else { + return ERROR_PACKET; + } } debug('encoded %j as %s', obj, str); return str; } +function tryStringify(str) { + try { + return JSON.stringify(str); + } catch(e){ + return false; + } +} + /** * Encode packet as 'buffer sequence' by removing blobs, and * deconstructing packet into object with placeholders and diff --git a/test/parser.js b/test/parser.js index 42179d2..652aa7f 100644 --- a/test/parser.js +++ b/test/parser.js @@ -1,8 +1,6 @@ var parser = require('../index.js'); var expect = require('expect.js'); var helpers = require('./helpers.js'); -var encode = parser.encode; -var decode = parser.decode; describe('parser', function(){ @@ -61,6 +59,24 @@ describe('parser', function(){ }); }); + 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();