Skip to content

Commit

Permalink
Prevent zalgo bomb on bad socket while forwarding request
Browse files Browse the repository at this point in the history
  • Loading branch information
jwolski committed Jun 3, 2015
1 parent 6a72d81 commit 7162258
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
20 changes: 19 additions & 1 deletion lib/request-proxy/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ var rawHead = require('./util.js').rawHead;
var strHead = require('./util.js').strHead;
var TypedError = require('error/typed');

var ChannelDestroyedError = TypedError({
type: 'ringpop.request-proxy.channel-destroyed',
message: 'Channel was destroyed before forwarding attempt'
});

var MaxRetriesExceeded = TypedError({
type: 'ringpop.request-proxy.max-retries-exceeded',
message: 'Max number of retries exceeded. {maxRetries} were attempted',
Expand Down Expand Up @@ -223,12 +228,19 @@ RequestProxySend.prototype.scheduleRetry = function scheduleRetry(callback) {
RequestProxySend.prototype.send = function send(channelOpts, callback) {
var self = this;

if (this.ringpop.channel.destroyed) {
process.nextTick(function onTick() {
callback(ChannelDestroyedError());
});
return;
}

this.ringpop.channel.send(
channelOpts,
channelOpts.endpoint,
this.getStrHead(),
this.request.body,
this.maxRetries === 0 ? callback : onSend
this.maxRetries === 0 ? onSendNoRetries : onSend
);

this.ringpop.emit('requestProxy.requestProxied');
Expand All @@ -248,6 +260,12 @@ RequestProxySend.prototype.send = function send(channelOpts, callback) {

self.scheduleRetry(callback);
}

function onSendNoRetries(err, res1, res2) {
process.nextTick(function onTick() {
callback(err, res1, res2);
});
}
};

module.exports = function send(opts, callback) {
Expand Down
50 changes: 50 additions & 0 deletions test/integration/proxy-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -964,3 +964,53 @@ test('handles checksum failures', function t(assert) {
});
});
});

test('does not crash when forwarding request on closed socket', function t(assert) {
var ringpopOpts = {
requestProxyMaxRetries: 0
};

var cluster = allocCluster(ringpopOpts, function onReady() {
destroyAllSockets();

cluster.request({
host: 'one', key: cluster.keys.two
}, function onResponse(err, resp) {
assert.ifError(err);

cluster.destroy();
assert.end();
});
});

function destroyAllSockets() {
var allPeers = cluster.one.channel.peers;

Object.keys(allPeers).forEach(function each(key) {
allPeers[key][0].socket.destroy();
});
}
});

test('send on destroyed channel not allowed', function t(assert) {
var ringpopOpts = {
requestProxyMaxRetries: 0
};

var cluster = allocCluster(ringpopOpts, function onReady() {
cluster.one.channel.quit();

cluster.request({
host: 'one', key: cluster.keys.two
}, function onResponse(err, resp) {
assert.ifError(err);

assert.equal(resp.statusCode, 500);
assert.ok(resp.body.indexOf(
'Channel was destroyed before forwarding attempt') >= 0);

cluster.destroy();
assert.end();
});
});
});

0 comments on commit 7162258

Please sign in to comment.