Skip to content

Commit

Permalink
fix(deserializeStream): allow multiple documents to be deserialized
Browse files Browse the repository at this point in the history
deserializeStream was calling deserialize, which required the buffer
size to exactly match the object size per the corpus test. Fixing
this by adding a flag that deserializeStream passes to allow the
buffer to be larger than the object size.

Fixes #244
  • Loading branch information
daprahamian authored Apr 27, 2018
1 parent e068b5c commit 6fc5984
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 6 deletions.
5 changes: 3 additions & 2 deletions lib/bson/bson.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ BSON.prototype.serializeWithBufferAndIndex = function(object, finalBuffer, optio
* @param {Object} [options.promoteValues=false] when deserializing will promote BSON values to their Node.js closest equivalent types.
* @param {Object} [options.fieldsAsRaw=null] allow to specify if there what fields we wish to return as unserialized raw buffer.
* @param {Object} [options.bsonRegExp=false] return BSON regular expressions as BSONRegExp instances.
* @param {boolean} [options.allowObjectSmallerThanBufferSize=false] allows the buffer to be larger than the parsed BSON object
* @return {Object} returns the deserialized Javascript Object.
* @api public
*/
Expand Down Expand Up @@ -183,15 +184,15 @@ BSON.prototype.deserializeStream = function(
docStartIndex,
options
) {
options = options != null ? options : {};
options = Object.assign({ allowObjectSmallerThanBufferSize: true }, options);
var index = startIndex;
// Loop over all documents
for (var i = 0; i < numberOfDocuments; i++) {
// Find size of the document
var size =
data[index] | (data[index + 1] << 8) | (data[index + 2] << 16) | (data[index + 3] << 24);
// Update options with index
options['index'] = index;
options.index = index;
// Parse the document at this point
documents[docStartIndex + i] = this.deserialize(data, options);
// Adjust index by the document size
Expand Down
19 changes: 16 additions & 3 deletions lib/bson/parser/deserializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,22 @@ var deserialize = function(buffer, options, isArray) {
(buffer[index + 2] << 16) |
(buffer[index + 3] << 24);

// Ensure buffer is valid size
if (size < 5 || buffer.length !== size || size + index > buffer.length) {
throw new Error('corrupt bson message');
if (size < 5) {
throw new Error(`bson size must be >= 5, is ${size}`);
}

if (options.allowObjectSmallerThanBufferSize && buffer.length < size) {
throw new Error(`buffer length ${buffer.length} must be >= bson size ${size}`);
}

if (!options.allowObjectSmallerThanBufferSize && buffer.length !== size) {
throw new Error(`buffer length ${buffer.length} must === bson size ${size}`);
}

if (size + index > buffer.length) {
throw new Error(
`(bson size ${size} + options.index ${index} must be <= buffer length ${buffer.length})`
);
}

// Illegal end value
Expand Down
6 changes: 5 additions & 1 deletion test/binary_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ BinaryParser.decodeFloat = function decodeFloat(data, precisionBits, exponentBit
} while ((precisionBits -= startBit));

return exponent === (bias << 1) + 1
? significand ? NaN : signal ? -Infinity : +Infinity
? significand
? NaN
: signal
? -Infinity
: +Infinity
: (1 + signal * -2) *
(exponent || significand
? !exponent
Expand Down
17 changes: 17 additions & 0 deletions test/node/bson_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,23 @@ describe('BSON', function() {
// done();
// }

it('should properly deserialize multiple documents using deserializeStream', function() {
const bson = createBSON();
const docs = [{ foo: 'bar' }, { foo: 'baz' }, { foo: 'quux' }];

// Serialize the test data
const serializedDocs = [];
for (let i = 0; i < docs.length; i++) {
serializedDocs[i] = bson.serialize(docs[i]);
}
const buf = Buffer.concat(serializedDocs);

const parsedDocs = [];
bson.deserializeStream(buf, 0, docs.length, parsedDocs, 0);

docs.forEach((doc, i) => expect(doc).to.deep.equal(parsedDocs[i]));
});

/**
* @ignore
*/
Expand Down

0 comments on commit 6fc5984

Please sign in to comment.