Skip to content
Permalink
Browse files Browse the repository at this point in the history
Merge pull request #68 from SalesforceEng/fix-too-many-semicolons
Reduce parse time for many semicolons.
  • Loading branch information
stash-sfdc committed Jul 21, 2016
2 parents ce76918 + e4fc2e0 commit 6156272
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 12 deletions.
18 changes: 6 additions & 12 deletions lib/cookie.js
Expand Up @@ -68,9 +68,6 @@ var LOOSE_COOKIE_PAIR = /^((?:=)?([^=;]*)\s*=\s*)?([^\n\r\0]*)/;
// Note ';' is \x3B
var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;

// Used for checking whether or not there is a trailing semi-colon
var TRAILING_SEMICOLON = /;+$/;

var DAY_OF_MONTH = /^(\d{1,2})[^\d]*$/;
var TIME = /^(\d{1,2})[^\d]*:(\d{1,2})[^\d]*:(\d{1,2})[^\d]*$/;
var MONTH = /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/i;
Expand Down Expand Up @@ -327,12 +324,6 @@ function parse(str, options) {
}
str = str.trim();

// S4.1.1 Trailing semi-colons are not part of the specification.
var semiColonCheck = TRAILING_SEMICOLON.exec(str);
if (semiColonCheck) {
str = str.slice(0, semiColonCheck.index);
}

// We use a regex to parse the "name-value-pair" part of S5.2
var firstSemi = str.indexOf(';'); // S5.2 step 1
var pairRe = options.loose ? LOOSE_COOKIE_PAIR : COOKIE_PAIR;
Expand Down Expand Up @@ -362,7 +353,7 @@ function parse(str, options) {
// S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
// (including the %x3B (";") in question)." plus later on in the same section
// "discard the first ";" and trim".
var unparsed = str.slice(firstSemi).replace(/^\s*;\s*/,'').trim();
var unparsed = str.slice(firstSemi + 1).trim();

// "If the unparsed-attributes string is empty, skip the rest of these
// steps."
Expand All @@ -378,9 +369,12 @@ function parse(str, options) {
* cookie-attribute-list". Therefore, in this implementation, we overwrite
* the previous value.
*/
var cookie_avs = unparsed.split(/\s*;\s*/);
var cookie_avs = unparsed.split(';');
while (cookie_avs.length) {
var av = cookie_avs.shift();
var av = cookie_avs.shift().trim();
if (av.length === 0) { // happens if ";;" appears
continue;
}
var av_sep = av.indexOf('=');
var av_key, av_value;

Expand Down
13 changes: 13 additions & 0 deletions test/parsing_test.js
Expand Up @@ -322,6 +322,19 @@ vows
"no path": function(c) { assert.equal(c.path, null) },
"no domain": function(c) { assert.equal(c.domain, null) },
"no extensions": function(c) { assert.ok(!c.extensions) }
},
"way too many semicolons followed by non-semicolon": {
topic: function() {
// takes abnormally long due to semi-catastrophic regexp backtracking
var str = 'foo=bar' + (';'.repeat(65535)) + ' domain=example.com';
return Cookie.parse(str) || null;
},
"parsed": function(c) { assert.ok(c) },
"key": function(c) { assert.equal(c.key, 'foo') },
"value": function(c) { assert.equal(c.value, 'bar') },
"no path": function(c) { assert.equal(c.path, null) },
"no domain": function(c) { assert.equal(c.domain, 'example.com') },
"no extensions": function(c) { assert.ok(!c.extensions) }
}
})
.export(module);

0 comments on commit 6156272

Please sign in to comment.