diff --git a/lib/cookie.js b/lib/cookie.js index ad1ef3ee..bfd228d2 100644 --- a/lib/cookie.js +++ b/lib/cookie.js @@ -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]+$/; @@ -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 @@ -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 @@ -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 */ diff --git a/test/date_test.js b/test/date_test.js index afd989c5..c52aa85a 100644 --- a/test/date_test.js +++ b/test/date_test.js @@ -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({ @@ -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, @@ -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);