From 4da1e0b4e0ea8ea5d34185463ed295125d6ae5ca Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 11 Jan 2017 14:55:45 -0800 Subject: [PATCH] bloom: do not allow passed in buffer. --- lib/utils/bloom.js | 86 +++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/lib/utils/bloom.js b/lib/utils/bloom.js index 07a46c3a..a8f696c2 100644 --- a/lib/utils/bloom.js +++ b/lib/utils/bloom.js @@ -27,7 +27,7 @@ var LN2 = 0.6931471805599453094172321214581765680755001343602552; * Bloom Filter * @exports Bloom * @constructor - * @param {Number|Buffer} bits - Filter size in bits, or filter itself. + * @param {Number} size - Filter size in bits. * @param {Number} n - Number of hash functions. * @param {Number} tweak - Seed value. * @param {Number|String} - Update type. @@ -38,9 +38,9 @@ var LN2 = 0.6931471805599453094172321214581765680755001343602552; * @property {Number} update - Update flag (see {@link Bloom.flags}). */ -function Bloom(bits, n, tweak, update) { +function Bloom(size, n, tweak, update) { if (!(this instanceof Bloom)) - return new Bloom(bits, n, tweak, update); + return new Bloom(size, n, tweak, update); this.filter = DUMMY; this.size = 0; @@ -48,10 +48,26 @@ function Bloom(bits, n, tweak, update) { this.tweak = 0; this.update = Bloom.flags.NONE; - if (bits != null) - this.fromOptions(bits, n, tweak, update); + if (size != null) + this.fromOptions(size, n, tweak, update); } +/** + * Max bloom filter size. + * @const {Number} + * @default + */ + +Bloom.MAX_BLOOM_FILTER_SIZE = 36000; + +/** + * Max number of hash functions. + * @const {Number} + * @default + */ + +Bloom.MAX_HASH_FUNCS = 50; + /** * Bloom filter update flags. * @enum {Number} @@ -90,46 +106,27 @@ Bloom.flagsByVal = { 2: 'PUBKEY_ONLY' }; -/** - * Max bloom filter size. - * @const {Number} - * @default - */ - -Bloom.MAX_BLOOM_FILTER_SIZE = 36000; - -/** - * Max number of hash functions. - * @const {Number} - * @default - */ - -Bloom.MAX_HASH_FUNCS = 50; - /** * Inject properties from options. * @private - * @param {Number|Buffer} bits - Filter size in bits, or filter itself. + * @param {Number} size - Filter size in bits. * @param {Number} n - Number of hash functions. * @param {Number} tweak - Seed value. * @param {Number|String} - Update type. * @returns {Bloom} */ -Bloom.prototype.fromOptions = function fromOptions(bits, n, tweak, update) { - var filter, size; +Bloom.prototype.fromOptions = function fromOptions(size, n, tweak, update) { + var filter; - if (Buffer.isBuffer(bits)) { - filter = bits; - size = filter.length * 8; - } else { - assert(typeof bits === 'number', '`bits` must be a number or Buffer.'); - assert(bits > 0, '`bits` must be greater than zero.'); - size = bits; - size -= size % 8; - filter = new Buffer(size / 8); - filter.fill(0); - } + assert(typeof size === 'number', '`size` must be a number.'); + assert(size > 0, '`size` must be greater than zero.'); + assert(size % 1 === 0, '`size` must be an integer.'); + + size -= size % 8; + + filter = new Buffer(size / 8); + filter.fill(0); if (tweak == null || tweak === -1) tweak = (Math.random() * 0x100000000) >>> 0; @@ -144,7 +141,9 @@ Bloom.prototype.fromOptions = function fromOptions(bits, n, tweak, update) { assert(size > 0, '`size` must be greater than zero.'); assert(n > 0, '`n` must be greater than zero.'); + assert(n % 1 === 0, '`n` must be an integer.'); assert(typeof tweak === 'number', '`tweak` must be a number.'); + assert(tweak % 1 === 0, '`tweak` must be an integer.'); assert(Bloom.flagsByVal[update], 'Unknown update flag.'); this.filter = filter; @@ -158,15 +157,15 @@ Bloom.prototype.fromOptions = function fromOptions(bits, n, tweak, update) { /** * Instantiate bloom filter from options. - * @param {Number|Buffer} bits - Filter size in bits, or filter itself. + * @param {Number} size - Filter size in bits. * @param {Number} n - Number of hash functions. * @param {Number} tweak - Seed value. * @param {Number|String} - Update type. * @returns {Bloom} */ -Bloom.fromOptions = function fromOptions(bits, n, tweak, update) { - return new Bloom().fromOptions(bits, n, tweak, update); +Bloom.fromOptions = function fromOptions(size, n, tweak, update) { + return new Bloom().fromOptions(size, n, tweak, update); }; /** @@ -266,6 +265,12 @@ Bloom.prototype.added = function added(val, enc) { Bloom.fromRate = function fromRate(items, rate, update) { var size, n; + assert(typeof items === 'number', '`items` must be a number.'); + assert(items > 0, '`items` must be greater than zero.'); + assert(items % 1 === 0, '`items` must be an integer.'); + assert(typeof rate === 'number', '`rate` must be a number.'); + assert(rate >= 0 && rate <= 1, '`rate` must be between 0.0 and 1.0.'); + size = (-1 / LN2SQUARED * items * Math.log(rate)) | 0; if (update !== -1) @@ -409,12 +414,13 @@ function RollingFilter(items, rate) { */ RollingFilter.prototype.fromRate = function fromRate(items, rate) { - var logRate, max, n, limit, size, items, tweak, filter; + var logRate, max, n, limit, size, tweak, filter; assert(typeof items === 'number', '`items` must be a number.'); assert(items > 0, '`items` must be greater than zero.'); + assert(items % 1 === 0, '`items` must be an integer.'); assert(typeof rate === 'number', '`rate` must be a number.'); - assert(rate >= 0, '`rate` must be positive.'); + assert(rate >= 0 && rate <= 1, '`rate` must be between 0.0 and 1.0.'); logRate = Math.log(rate);