Uploaded image for project: 'Node.js Driver'
  1. Node.js Driver
  2. NODE-2384

BSON Double and Int32 types do not handle Number Objects gracefully

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • bson-4.0.3
    • Affects Version/s: 3.4.0
    • Component/s: None

      BSON objects do not handle number objects well. In the case of the Double BSON objects, the result will be a NaN. In the case of an Int32 BSON object, the result will always be zero.  Take the following code:

      const MongoClient = require('mongodb').MongoClient;
      const bson = require('bson');
      const assert = require('assert');
      
      const url = 'mongodb://localhost:27017/bsonObjectFail?useUnifiedTopology=true';
      const client = new MongoClient(url);
      
      (async function () {
       console.log('Start!');
       await client.connect();
       try {
       await client.db().dropDatabase(); // Drop DB for a clean slate.
      
      const db = client.db();
       const coll = db.collection('test'); 
       await coll.insertOne(\{a: new bson.Double(3.14)}); // This results in 3.14 
       await coll.insertOne(\{a: new bson.Double(new Number(3.14))});// This results in NaN
      
      // Verify sanity 
       const countPromises = [
       coll.countDocuments(\{ a: { $type: 'double' } }),
       coll.countDocuments(\{ a: 3.14 }),
       coll.countDocuments(\{ a: NaN }),
       ];
      
      const [doubleCount, threeCount, nanCount] = await Promise.all(countPromises);
       console.log('Double count:', doubleCount);
       console.log('\{ a: 3.14 } count:', threeCount);
       console.log('\{ a: NaN } count:', nanCount);
      
      console.log('Done!');
       } catch(err) {
       console.error(`Unexpected Error: ${err.stack}`);
       } finally {
       await client.close();
       }
      })();
      

      In an ideal world where BSON handles the Number object the output would look like this:

      Double count: 2
      { a: 3.14 } count: 2
      { a: NaN } count: 0
      

      However since it does not you get this instead:

      Double count: 2
      { a: 3.14 } count: 1
      { a: NaN } count: 1
      

      This can lead to very confusing errors along with data corruption if a user doesn't explicitly know that they need to pass the primitive number value to BSON. Suggest either adding an assert to the value or using something like `Number(value)` in the constructor to ensure that the number is converted to a primitive.

            Assignee:
            matt.broadstone@mongodb.com Matt Broadstone
            Reporter:
            andrew.stiegmann@airfordable.com Andrew Stiegmann
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: