From 5c08f18d365b64063bfbfa686cbb97cdd6267347 Mon Sep 17 00:00:00 2001 From: Manuel Jasso Date: Tue, 28 Aug 2018 16:07:08 -0700 Subject: [PATCH] Prevent ReDoS To fix https://github.com/lodash/lodash/issues/3359, modified reHasUnicodeWord to remove an unnecessary comma which made the regex greedy, this is only a test regex and not a matching regex. Added unit tests, this now should run under 5 ms instead of over 1000 ms for huge 50k+ char words. --- lodash.js | 2 +- test/test.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lodash.js b/lodash.js index c7081ddef..0bda583bb 100644 --- a/lodash.js +++ b/lodash.js @@ -276,7 +276,7 @@ var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); /** Used to detect strings that need a more robust regexp to match words. */ - var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; /** Used to assign default `context` object properties. */ var contextProps = [ diff --git a/test/test.js b/test/test.js index 822d229e0..149653f51 100644 --- a/test/test.js +++ b/test/test.js @@ -25358,6 +25358,22 @@ assert.deepEqual(actual, [['a'], ['b'], ['c']]); }); + + var maxMs = 5; + QUnit.test(`should take less than ${maxMs} ms to prevent ReDoS`, function(assert) { + assert.expect(3); + + var hugeWordLen = 50000; + var hugeWord = 'A'.repeat(hugeWordLen); + var startTime = Date.now(); + assert.deepEqual(_.words(hugeWord+'AeiouAreVowels'), [hugeWord, 'Aeiou', 'Are', 'Vowels']); + assert.deepEqual(_.words(hugeWord+'ÆiouAreVowels'), [hugeWord, 'Æiou', 'Are', 'Vowels']); + var endTime = Date.now(); + var timeSpent = endTime - startTime; + + assert.ok(timeSpent < maxMs, `operation took ${timeSpent} ms`); + }); + }()); /*--------------------------------------------------------------------------*/