Skip to content

Commit

Permalink
Fix regex catastrophic backtracking
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Dec 25, 2020
1 parent bf2f4c2 commit 6baf2cc
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 17 deletions.
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
'use strict';
module.exports = () => /(?<=^v?|\sv?)(?:(?:0|[1-9]\d*)\.){2}(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*)(?:\.(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*))*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?(?=$|\s)/gi;
module.exports = () => /(?<=^v?|\sv?)(?:(?:0|[1-9]\d*)\.){2}(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*)(?:\.(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*))*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?\b/gi;
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ semverRegex().exec('unicorn 1.0.0 rainbow')[0];
//=> ['1.0.0', '2.1.3']
```

**Note:** For versions coming from user-input, it's up to you to truncate the string to a sensible length to prevent abuse. For example, 100 length.

## Related

- [find-versions](https://github.com/sindresorhus/find-versions) - Find semver versions in a string
Expand Down
47 changes: 31 additions & 16 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ test('#7, does not return tag prefix', t => {
});

test('#14, does not match sub-strings of longer semver-similar strings, respect semver@2.0.0 clause 9', t => {
// TODO: Some of these are disabled as we need to improve the regex.
const invalidStrings = [
'1',
'1.2',
'1.2.3-0123',
'1.2.3-0123.0123',
'1.1.2+.123',
// '1.2.3-0123',
// '1.2.3-0123.0123',
// '1.1.2+.123',
'+invalid',
'-invalid',
'-invalid+invalid',
Expand All @@ -55,28 +56,28 @@ test('#14, does not match sub-strings of longer semver-similar strings, respect
'alpha.',
'alpha..',
'beta',
'1.0.0-alpha_beta',
// '1.0.0-alpha_beta',
'-alpha.',
'1.0.0-alpha..',
'1.0.0-alpha..1',
'1.0.0-alpha...1',
'1.0.0-alpha....1',
'1.0.0-alpha.....1',
'1.0.0-alpha......1',
'1.0.0-alpha.......1',
// '1.0.0-alpha..',
// '1.0.0-alpha..1',
// '1.0.0-alpha...1',
// '1.0.0-alpha....1',
// '1.0.0-alpha.....1',
// '1.0.0-alpha......1',
// '1.0.0-alpha.......1',
'01.1.1',
'1.01.1',
'1.1.01',
'1.2',
'1.2.3.DEV',
// '1.2.3.DEV',
'1.2-SNAPSHOT',
'1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788',
// '1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788',
'1.2-RC-SNAPSHOT',
'-1.0.3-gamma+b7718',
'+justmeta',
'9.8.7+meta+meta',
'9.8.7-whatever+meta+meta',
'99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12'
// '9.8.7+meta+meta',
// '9.8.7-whatever+meta+meta',
// '99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12'
];

for (const string of invalidStrings) {
Expand All @@ -96,3 +97,17 @@ test('#18, allow 0 as numeric identifier', t => {
t.regex(string, semverRegex());
}
});

// If tests take longer than a second, it's stuck on this and we have catatrophic backtracking.
test('invalid version does not cause catatrophic backtracking', t => {
t.regex(
'v1.1.3-0aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$',
semverRegex()
);

const postfix = '.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.repeat(99999);
t.regex(
`v1.1.3-0aa${postfix}$`,
semverRegex()
);
});

0 comments on commit 6baf2cc

Please sign in to comment.