Skip to content

Commit 89209b8

Browse files
author
Ruben Bridgewater
committed
Handle very big pipelines without crashing
1 parent cc540db commit 89209b8

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function RedisClient (options) {
106106
this.times_connected = 0;
107107
this.options = options;
108108
// Init parser
109-
this.reply_parser = new Parser({
109+
this.reply_parser = Parser({
110110
returnReply: function (data) {
111111
self.return_reply(data);
112112
},
@@ -786,8 +786,13 @@ RedisClient.prototype.send_command = function (command, args, callback) {
786786
};
787787

788788
RedisClient.prototype.writeDefault = RedisClient.prototype.writeStrings = function (data) {
789-
var command, str = '';
790-
while (command = this.pipeline_queue.shift()) {
789+
var str = '';
790+
for (var command = this.pipeline_queue.shift(); command; command = this.pipeline_queue.shift()) {
791+
// Write to stream if the string is bigger than 4mb. The biggest string may be Math.pow(2, 28) - 15 chars long
792+
if (str.length + command.length > 4 * 1024 * 1024) {
793+
this.stream.write(str);
794+
str = '';
795+
}
791796
str += command;
792797
}
793798
this.should_buffer = !this.stream.write(str + data);

test/multi.spec.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ describe("The 'multi' method", function () {
7070
});
7171
});
7272

73+
describe('pipeline limit', function () {
74+
75+
it('do not exceed maximum string size', function (done) {
76+
this.timeout(12000); // Windows tests on 0.10 are slow
77+
// Triggers a RangeError: Invalid string length if not handled properly
78+
client = redis.createClient();
79+
var multi = client.multi();
80+
var i = Math.pow(2, 28);
81+
while (i > 0) {
82+
i -= 10230;
83+
multi.set('foo' + i, 'bar' + new Array(1024).join('1234567890'));
84+
}
85+
client.on('ready', function () {
86+
multi.exec(function (err, res) {
87+
assert.strictEqual(res.length, 26241);
88+
});
89+
client.flushdb(done);
90+
});
91+
});
92+
93+
});
94+
7395
helper.allTests(function(parser, ip, args) {
7496

7597
describe("using " + parser + " and " + ip, function () {

0 commit comments

Comments
 (0)