From 89209b8adc48cd15cc6784605c22a01b1edb3002 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 1 Mar 2016 16:57:32 +0100 Subject: [PATCH] Handle very big pipelines without crashing --- index.js | 11 ++++++++--- test/multi.spec.js | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 57d0c65088..ba2a78e02c 100644 --- a/index.js +++ b/index.js @@ -106,7 +106,7 @@ function RedisClient (options) { this.times_connected = 0; this.options = options; // Init parser - this.reply_parser = new Parser({ + this.reply_parser = Parser({ returnReply: function (data) { self.return_reply(data); }, @@ -786,8 +786,13 @@ RedisClient.prototype.send_command = function (command, args, callback) { }; RedisClient.prototype.writeDefault = RedisClient.prototype.writeStrings = function (data) { - var command, str = ''; - while (command = this.pipeline_queue.shift()) { + var str = ''; + for (var command = this.pipeline_queue.shift(); command; command = this.pipeline_queue.shift()) { + // Write to stream if the string is bigger than 4mb. The biggest string may be Math.pow(2, 28) - 15 chars long + if (str.length + command.length > 4 * 1024 * 1024) { + this.stream.write(str); + str = ''; + } str += command; } this.should_buffer = !this.stream.write(str + data); diff --git a/test/multi.spec.js b/test/multi.spec.js index 766d579875..181cdf87d5 100644 --- a/test/multi.spec.js +++ b/test/multi.spec.js @@ -70,6 +70,28 @@ describe("The 'multi' method", function () { }); }); + describe('pipeline limit', function () { + + it('do not exceed maximum string size', function (done) { + this.timeout(12000); // Windows tests on 0.10 are slow + // Triggers a RangeError: Invalid string length if not handled properly + client = redis.createClient(); + var multi = client.multi(); + var i = Math.pow(2, 28); + while (i > 0) { + i -= 10230; + multi.set('foo' + i, 'bar' + new Array(1024).join('1234567890')); + } + client.on('ready', function () { + multi.exec(function (err, res) { + assert.strictEqual(res.length, 26241); + }); + client.flushdb(done); + }); + }); + + }); + helper.allTests(function(parser, ip, args) { describe("using " + parser + " and " + ip, function () {