You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					163 lines
				
				4.0 KiB
			
		
		
			
		
	
	
					163 lines
				
				4.0 KiB
			| 
											3 years ago
										 | 'use strict'; | ||
|  | 
 | ||
|  | var Buffer = require('safe-buffer').Buffer; | ||
|  | var utils = require('../lib/utils'); | ||
|  | var assert = require('assert'); | ||
|  | var debug = require('debug'); | ||
|  | 
 | ||
|  | var mongo; | ||
|  | try { | ||
|  |   mongo = new require('mongodb'); | ||
|  | } catch (e) { | ||
|  |   debug('mongo', 'cannot construct mongodb instance'); | ||
|  | } | ||
|  | 
 | ||
|  | describe('lib/utils', function() { | ||
|  |   describe('clone', function() { | ||
|  |     it('clones constructors named ObjectId', function(done) { | ||
|  |       function ObjectId(id) { | ||
|  |         this.id = id; | ||
|  |       } | ||
|  | 
 | ||
|  |       var o1 = new ObjectId('1234'); | ||
|  |       var o2 = utils.clone(o1); | ||
|  |       assert.ok(o2 instanceof ObjectId); | ||
|  | 
 | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('clones constructors named ObjectID', function(done) { | ||
|  |       function ObjectID(id) { | ||
|  |         this.id = id; | ||
|  |       } | ||
|  | 
 | ||
|  |       var o1 = new ObjectID('1234'); | ||
|  |       var o2 = utils.clone(o1); | ||
|  | 
 | ||
|  |       assert.ok(o2 instanceof ObjectID); | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('does not clone constructors named ObjectIdd', function(done) { | ||
|  |       function ObjectIdd(id) { | ||
|  |         this.id = id; | ||
|  |       } | ||
|  | 
 | ||
|  |       var o1 = new ObjectIdd('1234'); | ||
|  |       var o2 = utils.clone(o1); | ||
|  |       assert.ok(!(o2 instanceof ObjectIdd)); | ||
|  | 
 | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('optionally clones ObjectId constructors using its clone method', function(done) { | ||
|  |       function ObjectID(id) { | ||
|  |         this.id = id; | ||
|  |         this.cloned = false; | ||
|  |       } | ||
|  | 
 | ||
|  |       ObjectID.prototype.clone = function() { | ||
|  |         var ret = new ObjectID(this.id); | ||
|  |         ret.cloned = true; | ||
|  |         return ret; | ||
|  |       }; | ||
|  | 
 | ||
|  |       var id = 1234; | ||
|  |       var o1 = new ObjectID(id); | ||
|  |       assert.equal(id, o1.id); | ||
|  |       assert.equal(false, o1.cloned); | ||
|  | 
 | ||
|  |       var o2 = utils.clone(o1); | ||
|  |       assert.ok(o2 instanceof ObjectID); | ||
|  |       assert.equal(id, o2.id); | ||
|  |       assert.ok(o2.cloned); | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('clones mongodb.ReadPreferences', function(done) { | ||
|  |       if (!mongo) return done(); | ||
|  | 
 | ||
|  |       var tags = [ | ||
|  |         {dc: 'tag1'} | ||
|  |       ]; | ||
|  |       var prefs = [ | ||
|  |         new mongo.ReadPreference('primary'), | ||
|  |         new mongo.ReadPreference(mongo.ReadPreference.PRIMARY_PREFERRED), | ||
|  |         new mongo.ReadPreference('secondary', tags) | ||
|  |       ]; | ||
|  | 
 | ||
|  |       var prefsCloned = utils.clone(prefs); | ||
|  | 
 | ||
|  |       for (var i = 0; i < prefsCloned.length; i++) { | ||
|  |         assert.notEqual(prefs[i], prefsCloned[i]); | ||
|  |         if (prefs[i].tags) { | ||
|  |           assert.ok(prefsCloned[i].tags); | ||
|  |           assert.notEqual(prefs[i].tags, prefsCloned[i].tags); | ||
|  |           assert.notEqual(prefs[i].tags[0], prefsCloned[i].tags[0]); | ||
|  |         } else { | ||
|  |           assert.equal(prefsCloned[i].tags, null); | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('clones mongodb.Binary', function(done) { | ||
|  |       if (!mongo) return done(); | ||
|  |       var buf = Buffer.from('hi'); | ||
|  |       var binary = new mongo.Binary(buf, 2); | ||
|  |       var clone = utils.clone(binary); | ||
|  |       assert.equal(binary.sub_type, clone.sub_type); | ||
|  |       assert.equal(String(binary.buffer), String(buf)); | ||
|  |       assert.ok(binary !== clone); | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('handles objects with no constructor', function(done) { | ||
|  |       var name = '335'; | ||
|  | 
 | ||
|  |       var o = Object.create(null); | ||
|  |       o.name = name; | ||
|  | 
 | ||
|  |       var clone; | ||
|  |       assert.doesNotThrow(function() { | ||
|  |         clone = utils.clone(o); | ||
|  |       }); | ||
|  | 
 | ||
|  |       assert.equal(name, clone.name); | ||
|  |       assert.ok(o != clone); | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('handles buffers', function(done) { | ||
|  |       var buff = Buffer.alloc(10); | ||
|  |       buff.fill(1); | ||
|  |       var clone = utils.clone(buff); | ||
|  | 
 | ||
|  |       for (var i = 0; i < buff.length; i++) { | ||
|  |         assert.equal(buff[i], clone[i]); | ||
|  |       } | ||
|  | 
 | ||
|  |       done(); | ||
|  |     }); | ||
|  | 
 | ||
|  |     it('skips __proto__', function() { | ||
|  |       var payload = JSON.parse('{"__proto__": {"polluted": "vulnerable"}}'); | ||
|  |       var res = utils.clone(payload); | ||
|  | 
 | ||
|  |       assert.strictEqual({}.polluted, void 0); | ||
|  |       assert.strictEqual(res.__proto__, Object.prototype); | ||
|  |     }); | ||
|  |   }); | ||
|  | 
 | ||
|  |   describe('merge', function() { | ||
|  |     it('avoids prototype pollution', function() { | ||
|  |       var payload = JSON.parse('{"__proto__": {"polluted": "vulnerable"}}'); | ||
|  |       var obj = {}; | ||
|  |       utils.merge(obj, payload); | ||
|  | 
 | ||
|  |       assert.strictEqual({}.polluted, void 0); | ||
|  |     }); | ||
|  |   }); | ||
|  | }); |