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
						
					
					
				| '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);
 | |
|     });
 | |
|   });
 | |
| });
 |