@@ -50977,11 +50977,39 @@ var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
5097750977// Max safe segment length for coercion.
5097850978var MAX_SAFE_COMPONENT_LENGTH = 16
5097950979
50980+ var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6
50981+
5098050982// The actual regexps go on exports.re
5098150983var re = exports.re = []
50984+ var safeRe = exports.safeRe = []
5098250985var src = exports.src = []
5098350986var R = 0
5098450987
50988+ var LETTERDASHNUMBER = '[a-zA-Z0-9-]'
50989+
50990+ // Replace some greedy regex tokens to prevent regex dos issues. These regex are
50991+ // used internally via the safeRe object since all inputs in this library get
50992+ // normalized first to trim and collapse all extra whitespace. The original
50993+ // regexes are exported for userland consumption and lower level usage. A
50994+ // future breaking change could export the safer regex only with a note that
50995+ // all input should have extra whitespace removed.
50996+ var safeRegexReplacements = [
50997+ ['\\s', 1],
50998+ ['\\d', MAX_LENGTH],
50999+ [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
51000+ ]
51001+
51002+ function makeSafeRe (value) {
51003+ for (var i = 0; i < safeRegexReplacements.length; i++) {
51004+ var token = safeRegexReplacements[i][0]
51005+ var max = safeRegexReplacements[i][1]
51006+ value = value
51007+ .split(token + '*').join(token + '{0,' + max + '}')
51008+ .split(token + '+').join(token + '{1,' + max + '}')
51009+ }
51010+ return value
51011+ }
51012+
5098551013// The following Regular Expressions can be used for tokenizing,
5098651014// validating, and parsing SemVer version strings.
5098751015
@@ -50991,14 +51019,14 @@ var R = 0
5099151019var NUMERICIDENTIFIER = R++
5099251020src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'
5099351021var NUMERICIDENTIFIERLOOSE = R++
50994- src[NUMERICIDENTIFIERLOOSE] = '[0-9] +'
51022+ src[NUMERICIDENTIFIERLOOSE] = '\\d +'
5099551023
5099651024// ## Non-numeric Identifier
5099751025// Zero or more digits, followed by a letter or hyphen, and then zero or
5099851026// more letters, digits, or hyphens.
5099951027
5100051028var NONNUMERICIDENTIFIER = R++
51001- src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-] *'
51029+ src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-]' + LETTERDASHNUMBER + ' *'
5100251030
5100351031// ## Main Version
5100451032// Three dot-separated numeric identifiers.
@@ -51040,7 +51068,7 @@ src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
5104051068// Any combination of digits, letters, or hyphens.
5104151069
5104251070var BUILDIDENTIFIER = R++
51043- src[BUILDIDENTIFIER] = '[0-9A-Za-z-] +'
51071+ src[BUILDIDENTIFIER] = LETTERDASHNUMBER + ' +'
5104451072
5104551073// ## Build Metadata
5104651074// Plus sign, followed by one or more period-separated build metadata
@@ -51125,6 +51153,7 @@ src[LONETILDE] = '(?:~>?)'
5112551153var TILDETRIM = R++
5112651154src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'
5112751155re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g')
51156+ safeRe[TILDETRIM] = new RegExp(makeSafeRe(src[TILDETRIM]), 'g')
5112851157var tildeTrimReplace = '$1~'
5112951158
5113051159var TILDE = R++
@@ -51140,6 +51169,7 @@ src[LONECARET] = '(?:\\^)'
5114051169var CARETTRIM = R++
5114151170src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'
5114251171re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g')
51172+ safeRe[CARETTRIM] = new RegExp(makeSafeRe(src[CARETTRIM]), 'g')
5114351173var caretTrimReplace = '$1^'
5114451174
5114551175var CARET = R++
@@ -51161,6 +51191,7 @@ src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
5116151191
5116251192// this one has to use the /g flag
5116351193re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g')
51194+ safeRe[COMPARATORTRIM] = new RegExp(makeSafeRe(src[COMPARATORTRIM]), 'g')
5116451195var comparatorTrimReplace = '$1$2$3'
5116551196
5116651197// Something like `1.2.3 - 1.2.4`
@@ -51189,6 +51220,14 @@ for (var i = 0; i < R; i++) {
5118951220 debug(i, src[i])
5119051221 if (!re[i]) {
5119151222 re[i] = new RegExp(src[i])
51223+
51224+ // Replace all greedy whitespace to prevent regex dos issues. These regex are
51225+ // used internally via the safeRe object since all inputs in this library get
51226+ // normalized first to trim and collapse all extra whitespace. The original
51227+ // regexes are exported for userland consumption and lower level usage. A
51228+ // future breaking change could export the safer regex only with a note that
51229+ // all input should have extra whitespace removed.
51230+ safeRe[i] = new RegExp(makeSafeRe(src[i]))
5119251231 }
5119351232}
5119451233
@@ -51213,7 +51252,7 @@ function parse (version, options) {
5121351252 return null
5121451253 }
5121551254
51216- var r = options.loose ? re [LOOSE] : re [FULL]
51255+ var r = options.loose ? safeRe [LOOSE] : safeRe [FULL]
5121751256 if (!r.test(version)) {
5121851257 return null
5121951258 }
@@ -51268,7 +51307,7 @@ function SemVer (version, options) {
5126851307 this.options = options
5126951308 this.loose = !!options.loose
5127051309
51271- var m = version.trim().match(options.loose ? re [LOOSE] : re [FULL])
51310+ var m = version.trim().match(options.loose ? safeRe [LOOSE] : safeRe [FULL])
5127251311
5127351312 if (!m) {
5127451313 throw new TypeError('Invalid Version: ' + version)
@@ -51682,6 +51721,7 @@ function Comparator (comp, options) {
5168251721 return new Comparator(comp, options)
5168351722 }
5168451723
51724+ comp = comp.trim().split(/\s+/).join(' ')
5168551725 debug('comparator', comp, options)
5168651726 this.options = options
5168751727 this.loose = !!options.loose
@@ -51698,7 +51738,7 @@ function Comparator (comp, options) {
5169851738
5169951739var ANY = {}
5170051740Comparator.prototype.parse = function (comp) {
51701- var r = this.options.loose ? re [COMPARATORLOOSE] : re [COMPARATOR]
51741+ var r = this.options.loose ? safeRe [COMPARATORLOOSE] : safeRe [COMPARATOR]
5170251742 var m = comp.match(r)
5170351743
5170451744 if (!m) {
@@ -51812,17 +51852,24 @@ function Range (range, options) {
5181251852 this.loose = !!options.loose
5181351853 this.includePrerelease = !!options.includePrerelease
5181451854
51815- // First, split based on boolean or ||
51855+ // First reduce all whitespace as much as possible so we do not have to rely
51856+ // on potentially slow regexes like \s*. This is then stored and used for
51857+ // future error messages as well.
5181651858 this.raw = range
51817- this.set = range.split(/\s*\|\|\s*/).map(function (range) {
51859+ .trim()
51860+ .split(/\s+/)
51861+ .join(' ')
51862+
51863+ // First, split based on boolean or ||
51864+ this.set = this.raw.split('||').map(function (range) {
5181851865 return this.parseRange(range.trim())
5181951866 }, this).filter(function (c) {
5182051867 // throw out any that are not relevant for whatever reason
5182151868 return c.length
5182251869 })
5182351870
5182451871 if (!this.set.length) {
51825- throw new TypeError('Invalid SemVer Range: ' + range )
51872+ throw new TypeError('Invalid SemVer Range: ' + this.raw )
5182651873 }
5182751874
5182851875 this.format()
@@ -51841,28 +51888,23 @@ Range.prototype.toString = function () {
5184151888
5184251889Range.prototype.parseRange = function (range) {
5184351890 var loose = this.options.loose
51844- range = range.trim()
5184551891 // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
51846- var hr = loose ? re [HYPHENRANGELOOSE] : re [HYPHENRANGE]
51892+ var hr = loose ? safeRe [HYPHENRANGELOOSE] : safeRe [HYPHENRANGE]
5184751893 range = range.replace(hr, hyphenReplace)
5184851894 debug('hyphen replace', range)
5184951895 // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
51850- range = range.replace(re [COMPARATORTRIM], comparatorTrimReplace)
51851- debug('comparator trim', range, re [COMPARATORTRIM])
51896+ range = range.replace(safeRe [COMPARATORTRIM], comparatorTrimReplace)
51897+ debug('comparator trim', range, safeRe [COMPARATORTRIM])
5185251898
5185351899 // `~ 1.2.3` => `~1.2.3`
51854- range = range.replace(re [TILDETRIM], tildeTrimReplace)
51900+ range = range.replace(safeRe [TILDETRIM], tildeTrimReplace)
5185551901
5185651902 // `^ 1.2.3` => `^1.2.3`
51857- range = range.replace(re[CARETTRIM], caretTrimReplace)
51858-
51859- // normalize spaces
51860- range = range.split(/\s+/).join(' ')
51903+ range = range.replace(safeRe[CARETTRIM], caretTrimReplace)
5186151904
5186251905 // At this point, the range is completely trimmed and
5186351906 // ready to be split into comparators.
51864-
51865- var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]
51907+ var compRe = loose ? safeRe[COMPARATORLOOSE] : safeRe[COMPARATOR]
5186651908 var set = range.split(' ').map(function (comp) {
5186751909 return parseComparator(comp, this.options)
5186851910 }, this).join(' ').split(/\s+/)
@@ -51938,7 +51980,7 @@ function replaceTildes (comp, options) {
5193851980}
5193951981
5194051982function replaceTilde (comp, options) {
51941- var r = options.loose ? re [TILDELOOSE] : re [TILDE]
51983+ var r = options.loose ? safeRe [TILDELOOSE] : safeRe [TILDE]
5194251984 return comp.replace(r, function (_, M, m, p, pr) {
5194351985 debug('tilde', comp, _, M, m, p, pr)
5194451986 var ret
@@ -51979,7 +52021,7 @@ function replaceCarets (comp, options) {
5197952021
5198052022function replaceCaret (comp, options) {
5198152023 debug('caret', comp, options)
51982- var r = options.loose ? re [CARETLOOSE] : re [CARET]
52024+ var r = options.loose ? safeRe [CARETLOOSE] : safeRe [CARET]
5198352025 return comp.replace(r, function (_, M, m, p, pr) {
5198452026 debug('caret', comp, _, M, m, p, pr)
5198552027 var ret
@@ -52038,7 +52080,7 @@ function replaceXRanges (comp, options) {
5203852080
5203952081function replaceXRange (comp, options) {
5204052082 comp = comp.trim()
52041- var r = options.loose ? re [XRANGELOOSE] : re [XRANGE]
52083+ var r = options.loose ? safeRe [XRANGELOOSE] : safeRe [XRANGE]
5204252084 return comp.replace(r, function (ret, gtlt, M, m, p, pr) {
5204352085 debug('xRange', comp, ret, gtlt, M, m, p, pr)
5204452086 var xM = isX(M)
@@ -52108,10 +52150,10 @@ function replaceXRange (comp, options) {
5210852150function replaceStars (comp, options) {
5210952151 debug('replaceStars', comp, options)
5211052152 // Looseness is ignored here. star is always as loose as it gets!
52111- return comp.trim().replace(re [STAR], '')
52153+ return comp.trim().replace(safeRe [STAR], '')
5211252154}
5211352155
52114- // This function is passed to string.replace(re [HYPHENRANGE])
52156+ // This function is passed to string.replace(safeRe [HYPHENRANGE])
5211552157// M, m, patch, prerelease, build
5211652158// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
5211752159// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
@@ -52422,7 +52464,7 @@ function coerce (version) {
5242252464 return null
5242352465 }
5242452466
52425- var match = version.match(re [COERCE])
52467+ var match = version.match(safeRe [COERCE])
5242652468
5242752469 if (match == null) {
5242852470 return null
0 commit comments