Skip to content

Commit 6fc5984

Browse files
authored
fix(deserializeStream): allow multiple documents to be deserialized
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
1 parent e068b5c commit 6fc5984

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

Diff for: lib/bson/bson.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ BSON.prototype.serializeWithBufferAndIndex = function(object, finalBuffer, optio
128128
* @param {Object} [options.promoteValues=false] when deserializing will promote BSON values to their Node.js closest equivalent types.
129129
* @param {Object} [options.fieldsAsRaw=null] allow to specify if there what fields we wish to return as unserialized raw buffer.
130130
* @param {Object} [options.bsonRegExp=false] return BSON regular expressions as BSONRegExp instances.
131+
* @param {boolean} [options.allowObjectSmallerThanBufferSize=false] allows the buffer to be larger than the parsed BSON object
131132
* @return {Object} returns the deserialized Javascript Object.
132133
* @api public
133134
*/
@@ -183,15 +184,15 @@ BSON.prototype.deserializeStream = function(
183184
docStartIndex,
184185
options
185186
) {
186-
options = options != null ? options : {};
187+
options = Object.assign({ allowObjectSmallerThanBufferSize: true }, options);
187188
var index = startIndex;
188189
// Loop over all documents
189190
for (var i = 0; i < numberOfDocuments; i++) {
190191
// Find size of the document
191192
var size =
192193
data[index] | (data[index + 1] << 8) | (data[index + 2] << 16) | (data[index + 3] << 24);
193194
// Update options with index
194-
options['index'] = index;
195+
options.index = index;
195196
// Parse the document at this point
196197
documents[docStartIndex + i] = this.deserialize(data, options);
197198
// Adjust index by the document size

Diff for: lib/bson/parser/deserializer.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,22 @@ var deserialize = function(buffer, options, isArray) {
2323
(buffer[index + 2] << 16) |
2424
(buffer[index + 3] << 24);
2525

26-
// Ensure buffer is valid size
27-
if (size < 5 || buffer.length !== size || size + index > buffer.length) {
28-
throw new Error('corrupt bson message');
26+
if (size < 5) {
27+
throw new Error(`bson size must be >= 5, is ${size}`);
28+
}
29+
30+
if (options.allowObjectSmallerThanBufferSize && buffer.length < size) {
31+
throw new Error(`buffer length ${buffer.length} must be >= bson size ${size}`);
32+
}
33+
34+
if (!options.allowObjectSmallerThanBufferSize && buffer.length !== size) {
35+
throw new Error(`buffer length ${buffer.length} must === bson size ${size}`);
36+
}
37+
38+
if (size + index > buffer.length) {
39+
throw new Error(
40+
`(bson size ${size} + options.index ${index} must be <= buffer length ${buffer.length})`
41+
);
2942
}
3043

3144
// Illegal end value

Diff for: test/binary_parser.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ BinaryParser.decodeFloat = function decodeFloat(data, precisionBits, exponentBit
4747
} while ((precisionBits -= startBit));
4848

4949
return exponent === (bias << 1) + 1
50-
? significand ? NaN : signal ? -Infinity : +Infinity
50+
? significand
51+
? NaN
52+
: signal
53+
? -Infinity
54+
: +Infinity
5155
: (1 + signal * -2) *
5256
(exponent || significand
5357
? !exponent

Diff for: test/node/bson_test.js

+17
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,23 @@ describe('BSON', function() {
21742174
// done();
21752175
// }
21762176

2177+
it('should properly deserialize multiple documents using deserializeStream', function() {
2178+
const bson = createBSON();
2179+
const docs = [{ foo: 'bar' }, { foo: 'baz' }, { foo: 'quux' }];
2180+
2181+
// Serialize the test data
2182+
const serializedDocs = [];
2183+
for (let i = 0; i < docs.length; i++) {
2184+
serializedDocs[i] = bson.serialize(docs[i]);
2185+
}
2186+
const buf = Buffer.concat(serializedDocs);
2187+
2188+
const parsedDocs = [];
2189+
bson.deserializeStream(buf, 0, docs.length, parsedDocs, 0);
2190+
2191+
docs.forEach((doc, i) => expect(doc).to.deep.equal(parsedDocs[i]));
2192+
});
2193+
21772194
/**
21782195
* @ignore
21792196
*/

0 commit comments

Comments
 (0)