Skip to content

Commit

Permalink
Prevent the sequence count on a client from being larger then an uint…
Browse files Browse the repository at this point in the history
…32, which would cause a range error
  • Loading branch information
flippmoke committed Dec 12, 2019
1 parent f0ec720 commit b5ee4b0
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 15 deletions.
37 changes: 24 additions & 13 deletions lib/memjs/memjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Client.prototype.get = function(key, callback) {
});
}
var logger = this.options.logger;
this.seq++;
this.incrSeq();
var request = makeRequestBuffer(0, key, '', '', this.seq);
this.perform(key, request, this.seq, function(err, response) {
if (err) {
Expand Down Expand Up @@ -179,7 +179,7 @@ Client.prototype.set = function(key, value, options, callback) {
expires = options.expires;

// TODO: support flags, support version (CAS)
this.seq++;
this.incrSeq();
var expiration = makeExpiration(expires || this.options.expires);
var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]);
var request = makeRequestBuffer(1, key, extras, value, this.seq);
Expand Down Expand Up @@ -231,7 +231,7 @@ Client.prototype.add = function(key, value, options, callback) {
expires = options.expires;

// TODO: support flags, support version (CAS)
this.seq++;
this.incrSeq();
var expiration = makeExpiration(expires || this.options.expires);
var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]);
var request = makeRequestBuffer(2, key, extras, value, this.seq);
Expand Down Expand Up @@ -286,7 +286,7 @@ Client.prototype.replace = function(key, value, options, callback) {
expires = options.expires;

// TODO: support flags, support version (CAS)
this.seq++;
this.incrSeq();
var expiration = makeExpiration(expires || this.options.expires);
var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]);
var request = makeRequestBuffer(3, key, extras, value, this.seq);
Expand Down Expand Up @@ -325,7 +325,7 @@ Client.prototype.delete = function(key, callback) {
}
// TODO: Support version (CAS)
var logger = this.options.logger;
this.seq++;
this.incrSeq();
var request = makeRequestBuffer(4, key, '', '', this.seq);
this.perform(key, request, this.seq, function(err, response) {
if (err) {
Expand Down Expand Up @@ -385,7 +385,7 @@ Client.prototype.increment = function(key, amount, options, callback) {
expires = options.expires;

// TODO: support version (CAS)
this.seq++;
this.incrSeq();
initial = initial || 0;
expires = expires || this.options.expires;
var extras = makeAmountInitialAndExpiration(amount, initial, expires);
Expand Down Expand Up @@ -447,7 +447,7 @@ Client.prototype.decrement = function(key, amount, options, callback) {
initial = options.initial;
expires = options.expires;

this.seq++;
this.incrSeq();
initial = initial || 0;
expires = expires || this.options.expires;
var extras = makeAmountInitialAndExpiration(amount, initial, expires);
Expand Down Expand Up @@ -484,7 +484,7 @@ Client.prototype.append = function(key, value, callback) {
}
// TODO: support version (CAS)
var logger = this.options.logger;
this.seq++;
this.incrSeq();
var request = makeRequestBuffer(0x0E, key, '', value, this.seq);
this.perform(key, request, this.seq, function(err, response) {
if (err) {
Expand Down Expand Up @@ -520,7 +520,7 @@ Client.prototype.prepend = function(key, value, callback) {
}
// TODO: support version (CAS)
var logger = this.options.logger;
this.seq++;
this.incrSeq();
var request = makeRequestBuffer(0x0E, key, '', value, this.seq);
this.perform(key, request, this.seq, function(err, response) {
if (err) {
Expand Down Expand Up @@ -556,7 +556,7 @@ Client.prototype.touch = function(key, expires, callback) {
}
// TODO: support version (CAS)
var logger = this.options.logger;
this.seq++;
this.incrSeq();
var extras = makeExpiration(expires || this.options.expires);
var request = makeRequestBuffer(0x1C, key, extras, '', this.seq);
this.perform(key, request, this.seq, function(err, response) {
Expand Down Expand Up @@ -594,7 +594,7 @@ Client.prototype.flush = function(callback) {
return promisify(function(callback) { self.flush(function(err, results) { callback(err, results); }); });
}
// TODO: support expiration
this.seq++;
this.incrSeq();
var request = makeRequestBuffer(0x08, '', '', '', this.seq);
var count = this.servers.length;
var result = {};
Expand Down Expand Up @@ -636,7 +636,7 @@ Client.prototype.flush = function(callback) {
// mapping the stat name to the value of the statistic as a string.
Client.prototype.statsWithKey = function(key, callback) {
var logger = this.options.logger;
this.seq++;
this.incrSeq();
var request = makeRequestBuffer(0x10, key, '', '', this.seq);
var i;

Expand Down Expand Up @@ -712,7 +712,7 @@ Client.prototype.resetStats = function(callback) {
// fail and are retried, leading to the quit command winning and closing the
// connection before the retries complete.
Client.prototype.quit = function() {
this.seq++;
this.incrSeq();
// TODO: Nicer perhaps to do QUITQ (0x17) but need a new callback for when
// write is done.
var request = makeRequestBuffer(0x07, '', '', '', this.seq); // QUIT
Expand Down Expand Up @@ -796,6 +796,17 @@ Client.prototype.perform = function(key, request, seq, callback, retries) {
serv.write(request);
};

// Increment the seq value
Client.prototype.incrSeq = function() {
// Prevent seq from being larger than 2^31
// so that range errors do not occur. In event
// this occurs we simply roll over the value.
if (this.seq > Math.pow(2,31)) {
this.seq = 0;
}
this.seq++;
};

exports.Client = Client;
exports.Server = Server;
exports.Utils = require('./utils');
Expand Down
6 changes: 4 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions test/client_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -727,4 +727,30 @@ test('Failover', function(t) {
});

});

test('Very Large Client Seq', function(t) {
var n = 0;
var dummyServer = new MemJS.Server();
dummyServer.write = function(requestBuf) {
var request = MemJS.Utils.parseMessage(requestBuf);
t.equal('hello', request.key.toString());
t.equal('world', request.val.toString());
t.equal('0000000000000400', request.extras.toString('hex'));
n += 1;
dummyServer.respond({header: {status: 0, opaque: request.header.opaque}});
};

var client = new MemJS.Client([dummyServer], {expires: 1024});
client.seq = Math.pow(2,33);
var assertor = function(err, val) {
t.equal(null, err);
t.equal(true, val);
t.equal(1, n, 'Ensure add is called');
};
client.add('hello', 'world', {}, assertor);
n = 0;
return client.add('hello', 'world', {}).then(function(success) {
assertor(null, success);
});
});
return;

0 comments on commit b5ee4b0

Please sign in to comment.