utils.test.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. 'use strict';
  2. const utils = require('../lib/utils');
  3. const assert = require('assert');
  4. const debug = require('debug');
  5. let mongo;
  6. try {
  7. mongo = new require('mongodb');
  8. } catch (e) {
  9. debug('mongo', 'cannot construct mongodb instance');
  10. }
  11. describe('lib/utils', function() {
  12. describe('clone', function() {
  13. it('clones constructors named ObjectId', function(done) {
  14. function ObjectId(id) {
  15. this.id = id;
  16. }
  17. const o1 = new ObjectId('1234');
  18. const o2 = utils.clone(o1);
  19. assert.ok(o2 instanceof ObjectId);
  20. done();
  21. });
  22. it('clones constructors named ObjectID', function(done) {
  23. function ObjectID(id) {
  24. this.id = id;
  25. }
  26. const o1 = new ObjectID('1234');
  27. const o2 = utils.clone(o1);
  28. assert.ok(o2 instanceof ObjectID);
  29. done();
  30. });
  31. it('clones RegExp', function(done) {
  32. const sampleRE = /a/giy;
  33. const clonedRE = utils.clone(sampleRE);
  34. assert.ok(clonedRE !== sampleRE);
  35. assert.ok(clonedRE instanceof RegExp);
  36. assert.ok(clonedRE.source === 'a');
  37. assert.ok(clonedRE.flags === 'giy');
  38. done();
  39. });
  40. it('clones Buffer', function(done) {
  41. const buf1 = Buffer.alloc(10);
  42. const buf2 = utils.clone(buf1);
  43. assert.ok(buf2 instanceof Buffer);
  44. done();
  45. });
  46. it('does not clone constructors named ObjectIdd', function(done) {
  47. function ObjectIdd(id) {
  48. this.id = id;
  49. }
  50. const o1 = new ObjectIdd('1234');
  51. const o2 = utils.clone(o1);
  52. assert.ok(!(o2 instanceof ObjectIdd));
  53. done();
  54. });
  55. it('optionally clones ObjectId constructors using its clone method', function(done) {
  56. function ObjectID(id) {
  57. this.id = id;
  58. this.cloned = false;
  59. }
  60. ObjectID.prototype.clone = function() {
  61. const ret = new ObjectID(this.id);
  62. ret.cloned = true;
  63. return ret;
  64. };
  65. const id = 1234;
  66. const o1 = new ObjectID(id);
  67. assert.equal(id, o1.id);
  68. assert.equal(false, o1.cloned);
  69. const o2 = utils.clone(o1);
  70. assert.ok(o2 instanceof ObjectID);
  71. assert.equal(id, o2.id);
  72. assert.ok(o2.cloned);
  73. done();
  74. });
  75. it('clones mongodb.ReadPreferences', function(done) {
  76. if (!mongo) return done();
  77. const tags = [
  78. { dc: 'tag1' }
  79. ];
  80. const prefs = [
  81. new mongo.ReadPreference('primary'),
  82. new mongo.ReadPreference(mongo.ReadPreference.PRIMARY_PREFERRED),
  83. new mongo.ReadPreference('secondary', tags)
  84. ];
  85. const prefsCloned = utils.clone(prefs);
  86. for (let i = 0; i < prefsCloned.length; i++) {
  87. assert.notEqual(prefs[i], prefsCloned[i]);
  88. if (prefs[i].tags) {
  89. assert.ok(prefsCloned[i].tags);
  90. assert.notEqual(prefs[i].tags, prefsCloned[i].tags);
  91. assert.notEqual(prefs[i].tags[0], prefsCloned[i].tags[0]);
  92. } else {
  93. assert.equal(prefsCloned[i].tags, null);
  94. }
  95. }
  96. done();
  97. });
  98. it('clones mongodb.Binary', function(done) {
  99. if (!mongo) return done();
  100. const buf = Buffer.from('hi');
  101. const binary = new mongo.Binary(buf, 2);
  102. const clone = utils.clone(binary);
  103. assert.equal(binary.sub_type, clone.sub_type);
  104. assert.equal(String(binary.buffer), String(buf));
  105. assert.ok(binary !== clone);
  106. done();
  107. });
  108. it('handles objects with no constructor', function(done) {
  109. const name = '335';
  110. const o = Object.create(null);
  111. o.name = name;
  112. let clone;
  113. assert.doesNotThrow(function() {
  114. clone = utils.clone(o);
  115. });
  116. assert.equal(name, clone.name);
  117. assert.ok(o != clone);
  118. done();
  119. });
  120. it('handles buffers', function(done) {
  121. const buff = Buffer.alloc(10);
  122. buff.fill(1);
  123. const clone = utils.clone(buff);
  124. for (let i = 0; i < buff.length; i++) {
  125. assert.equal(buff[i], clone[i]);
  126. }
  127. done();
  128. });
  129. it('skips __proto__', function() {
  130. const payload = JSON.parse('{"__proto__": {"polluted": "vulnerable"}}');
  131. const res = utils.clone(payload);
  132. assert.strictEqual({}.polluted, void 0);
  133. assert.strictEqual(res.__proto__, Object.prototype);
  134. });
  135. });
  136. describe('merge', function() {
  137. it('avoids prototype pollution', function() {
  138. const payload = JSON.parse('{"__proto__": {"polluted": "vulnerable"}}');
  139. const obj = {};
  140. utils.merge(obj, payload);
  141. assert.strictEqual({}.polluted, void 0);
  142. });
  143. });
  144. });