Skip to content

Commit

Permalink
Avoid unbounded Regexp parts in date parsing
Browse files Browse the repository at this point in the history
Replaces a bunch of `[^\d]*$` with bounded `(?:[^\d]|$)`

Double checked the RFC6265 spec: time cannot have non-digits beside the
colons.
  • Loading branch information
stash-sfdc committed Sep 22, 2017
1 parent c9bd79d commit 2a4775c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 12 deletions.
19 changes: 12 additions & 7 deletions lib/cookie.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ try {
console.warn("cookie: can't load punycode; won't use punycode for domain normalization");
}

var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;

// From RFC6265 S4.1.1
// note that it excludes \x3B ";"
var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
Expand All @@ -61,10 +59,17 @@ var TERMINATORS = ['\n', '\r', '\0'];
// Note ';' is \x3B
var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;

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;
// date-time parsing constants (RFC6265 S5.1.1)

var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
var DAY_OF_MONTH = /^(\d{1,2})(?:[^\d]|$)/;

// S5.1.1 for "hms-time" -- is one or two digits each separated by :
// Cannot have non-digits beside the numbers like in other parts of the
// construction.
var TIME = /^(\d{1,2}):(\d{1,2}):(\d{1,2})(?:[^\d]|$)/; // only anchor at start

var MONTH = /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/i;
var MONTH_TO_NUM = {
jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
Expand All @@ -76,7 +81,7 @@ var NUM_TO_DAY = [
'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
];

var YEAR = /^(\d{2}|\d{4})$/; // 2 to 4 digits
var YEAR = /^(\d{2}|\d{4})(?:[^\d]|$)/; // 2 or 4 digits, anchored at start

var MAX_TIME = 2147483647000; // 31-bit max
var MIN_TIME = 0; // 31-bit min
Expand Down Expand Up @@ -146,7 +151,7 @@ function parseDate(str) {
if (day === null) {
result = DAY_OF_MONTH.exec(token);
if (result) {
day = parseInt(result, 10);
day = parseInt(result[1], 10);
/* RFC6265 S5.1.1.5:
* [fail if] the day-of-month-value is less than 1 or greater than 31
*/
Expand Down
54 changes: 49 additions & 5 deletions test/date_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,21 @@ function dateVows(table) {
Object.keys(table).forEach(function (date) {
var expect = table[date];
theVows[date] = function () {
var got = tough.parseDate(date) ? 'valid' : 'invalid';
assert.equal(got, expect ? 'valid' : 'invalid');
var got = tough.parseDate(date) ? true : false;
if (expect && !got) {
assert.ok(false, "expected valid date but was invalid");
} else if (!expect && got) {
assert.ok(false, "expected invalid date but was valid");
} else {
assert.ok(true);
}
};
});
return {"date parsing": theVows};
}

var TOO_MANY_XS = 'x'.repeat(65535);

vows
.describe('Date')
.addBatch(dateVows({
Expand All @@ -55,6 +63,7 @@ vows
"18 Oct 2011 07:42:42 GMT": true,
"8 Oct 2011 7:42:42 GMT": true,
"8 Oct 2011 7:2:42 GMT": true,
"8 Oct 2011 7:2:2 GMT": true,
"Oct 18 2011 07:42:42 GMT": true,
"Tue Oct 18 2011 07:05:03 GMT+0000 (GMT)": true,
"09 Jun 2021 10:18:14 GMT": true,
Expand All @@ -64,16 +73,51 @@ vows
'01 Jan 1601 00:00:00 GMT': true,
'10 Feb 81 13:00:00 GMT': true, // implicit year
'Thu, 17-Apr-2014 02:12:29 GMT': true, // dashes
'Thu, 17-Apr-2014 02:12:29 UTC': true // dashes and UTC
'Thu, 17-Apr-2014 02:12:29 UTC': true, // dashes and UTC

// garbage after parts:
"Wedxxx, 09 Jun 2021 10:18:14 GMT": true, // day of week doesn't matter
"Wed, 09e9 Jun 2021 10:18:14 GMT": true, // garbage after day ignored
"Wed, 09 Junxxx 2021 10:18:14 GMT": true, // prefix match on month
"Wed, 09 Jun 2021e9 10:18:14 GMT": true, // garbage after year OK
"Wed, 09 Jun 2021 10e9:18:14 GMT": false, // can't have garbage after HH
"Wed, 09 Jun 2021 10:18e9:14 GMT": false, // can't have garbage after MM
"Wed, 09 Jun 2021 10:18:14e9 GMT": true, // garbage after SS ignored

// extra digit in time parts:
"Thu, 01 Jan 1970 000:00:01 GMT": false,
"Thu, 01 Jan 1970 00:000:01 GMT": false,
"Thu, 01 Jan 1970 00:00:010 GMT": false,

"": false
}))
.addBatch({
"strict date parse of Thu, 01 Jan 1970 00:00:010 GMT": {
"reDos hr": {
topic: function () {
return tough.parseDate('Thu, 01 Jan 1970 00:00:010 GMT', true) ? true : false;
var str = "Wed, 09 Jun 2021 10" + TOO_MANY_XS + ":18:14 GMT";
return tough.parseDate(str, true) ? true : false;
},
"invalid": function (date) {
assert.equal(date, false);
}
},
"reDos min": {
topic: function () {
var str = "Wed, 09 Jun 2021 10:18" + TOO_MANY_XS + ":14 GMT";
return tough.parseDate(str, true) ? true : false;
},
"invalid": function (date) {
assert.equal(date, false);
}
},
"reDos sec": {
topic: function () {
var str = "Wed, 09 Jun 2021 10:18:14" + TOO_MANY_XS + " GMT";
return tough.parseDate(str, true) ? true : false;
},
"valid": function (date) {
assert.equal(date, true);
}
}
})
.export(module);

0 comments on commit 2a4775c

Please sign in to comment.