From 5c37d983820eff9ca9cc4361a7d96117a821580b Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 22 Sep 2021 18:30:24 -0700 Subject: [PATCH] fix: remediate ReDOS further --- index.js | 14 ++++++++++++-- test.js | 28 +++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 9aaa826..98bc55d 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,17 @@ 'use strict'; -var regex = /^(?:\r|\n)+|(?:\r|\n)+$/g; +var regex = /[^\r\n]/g; module.exports = function (str) { - return str.replace(regex, ''); + var result = regex.exec(str); + if (!result) { + return ''; + } + var firstIndex = result.index; + var lastIndex; + while (result) { + lastIndex = result.index + 1; + result = regex.exec(str); + } + return str.substring(firstIndex, lastIndex); }; diff --git a/test.js b/test.js index f4c9ffb..0c917f2 100644 --- a/test.js +++ b/test.js @@ -21,8 +21,34 @@ it('should trim off \\r\\n', function () { }); it('should not be susceptible to exponential backtracking', function () { + var redosString = 'a'; + var count = 1000; + while (count) { + redosString += '\r\n'; + count--; + } + redosString += 'a'; + var LongerRedosString = redosString; + var count = 1000; + while (count) { + LongerRedosString += redosString; + count--; + } var start = Date.now(); - trimOffNewlines('a' + '\r\n'.repeat(1000) + 'a'); + trimOffNewlines(redosString); + trimOffNewlines(LongerRedosString); var end = Date.now(); assert.ok(end - start < 1000, 'took too long, probably susceptible to ReDOS'); }); + +it('should leave newlines in the middle of a string alone', function () { + assert.strictEqual(trimOffNewlines('Come on,\nFhqwhgads.'), 'Come on,\nFhqwhgads.'); +}); + +it('should leave spaces at start and end alone', function () { + assert.strictEqual(trimOffNewlines(' fhqwhgads '), ' fhqwhgads '); +}); + +it('should return an empty string if there are only \\r and \\n', function () { + assert.strictEqual(trimOffNewlines('\r\n\r\r\n\n'), ''); +});