diff --git a/parser.js b/parser.js index c626b3e..f6a7ac8 100644 --- a/parser.js +++ b/parser.js @@ -288,6 +288,7 @@ Parser.prototype._parseSubscribe = function() { if (topic === null) return this._emitError(new Error('Parse error - cannot parse topic')) + if (this._pos >= packet.length) return this._emitError(new Error('Malformed Subscribe Payload')) qos = this._list.readUInt8(this._pos++) // Push pair to subscriptions diff --git a/test.js b/test.js index c5729da..9a33929 100644 --- a/test.js +++ b/test.js @@ -55,7 +55,8 @@ function testParseError(expected, fixture) { t.equal(err.message, expected, 'expected error message') }) - parser.on('packet', function() { + parser.on('packet', function(p) { + console.log(p) t.fail('parse errors should not be followed by packet events') }) @@ -993,3 +994,14 @@ test('stops parsing after first error', function(t) { 224, 0, // Header ])) }) + +// When a Subscribe packet contains a topic_filter and the given +// length is topic_filter.length + 1 then the last byte (requested QoS) is interpreted as topic_filter +// reading the requested_qos at the end causes 'Index out of range' read +testParseError('Malformed Subscribe Payload', Buffer.from([ + 130, 14, // subscribe header and remaining length + 0, 123, // packet ID + 0, 10, // topic filter length + 104, 105, 106, 107, 108, 47, 109, 110, 111, // topic filter with length of 9 bytes + 0 // requested QoS +]))