Skip to content

Commit

Permalink
Catch sparse arrays (#92)
Browse files Browse the repository at this point in the history
* Test with sparse arrays

* Throw informative error when encoding a sparse array
  • Loading branch information
ninevra committed Feb 11, 2021
1 parent 9fb92c3 commit 2a5e19d
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
18 changes: 17 additions & 1 deletion lib/encoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module.exports = function buildEncode (encodingTypes, options) {
// and Buffer-like objects
return bl([getBufferHeader(obj.length), obj])
}
if (Array.isArray(obj)) return bl().append([ getHeader(obj.length, 0x90, 0xdc), ...obj.map(encode) ])
if (Array.isArray(obj)) return encodeArray(obj, encode)
if (typeof obj === 'object') return encodeExt(obj, encodingTypes) || encodeObject(obj, options, encode)
if (typeof obj === 'number') return encodeNumber(obj, options)

Expand All @@ -44,6 +44,22 @@ module.exports = function buildEncode (encodingTypes, options) {
//
//

function encodeArray (array, encode) {
const acc = [ getHeader(array.length, 0x90, 0xdc) ]

// This has to be forEach; Array.prototype.map preserves missing values and
// Array.prototype.values yields them as undefined
array.forEach(item => {
acc.push(encode(item))
})

if (acc.length !== array.length + 1) {
throw new Error('Sparse arrays are not encodable in msgpack')
}

return bl(acc)
}

function encodeMap (map, options, encode) {
const acc = [ getHeader(map.size, 0x80, 0xde) ]
const keys = [ ...map.keys() ]
Expand Down
18 changes: 18 additions & 0 deletions test/sparse-arrays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict'

const test = require('tape').test
const msgpack = require('../')

test('throws when encoding sparse arrays', function (t) {
const encoder = msgpack()

t.deepEqual(encoder.decode(encoder.encode(new Array(0))), [])
t.throws(() => encoder.encode(new Array(1)), /Sparse arrays/)
t.throws(() => encoder.encode(new Array(100)), /Sparse arrays/)

const sparse = [1, 2, 3, 4]
delete sparse[3]
t.throws(() => encoder.encode(sparse), /Sparse arrays/)

t.end()
})

0 comments on commit 2a5e19d

Please sign in to comment.