@@ -56018,8 +56018,11 @@ var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
56018
56018
// Max safe segment length for coercion.
56019
56019
var MAX_SAFE_COMPONENT_LENGTH = 16
56020
56020
56021
+ var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6
56022
+
56021
56023
// The actual regexps go on exports.re
56022
56024
var re = exports.re = []
56025
+ var safeRe = exports.safeRe = []
56023
56026
var src = exports.src = []
56024
56027
var t = exports.tokens = {}
56025
56028
var R = 0
@@ -56028,6 +56031,31 @@ function tok (n) {
56028
56031
t[n] = R++
56029
56032
}
56030
56033
56034
+ var LETTERDASHNUMBER = '[a-zA-Z0-9-]'
56035
+
56036
+ // Replace some greedy regex tokens to prevent regex dos issues. These regex are
56037
+ // used internally via the safeRe object since all inputs in this library get
56038
+ // normalized first to trim and collapse all extra whitespace. The original
56039
+ // regexes are exported for userland consumption and lower level usage. A
56040
+ // future breaking change could export the safer regex only with a note that
56041
+ // all input should have extra whitespace removed.
56042
+ var safeRegexReplacements = [
56043
+ ['\\s', 1],
56044
+ ['\\d', MAX_LENGTH],
56045
+ [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
56046
+ ]
56047
+
56048
+ function makeSafeRe (value) {
56049
+ for (var i = 0; i < safeRegexReplacements.length; i++) {
56050
+ var token = safeRegexReplacements[i][0]
56051
+ var max = safeRegexReplacements[i][1]
56052
+ value = value
56053
+ .split(token + '*').join(token + '{0,' + max + '}')
56054
+ .split(token + '+').join(token + '{1,' + max + '}')
56055
+ }
56056
+ return value
56057
+ }
56058
+
56031
56059
// The following Regular Expressions can be used for tokenizing,
56032
56060
// validating, and parsing SemVer version strings.
56033
56061
@@ -56037,14 +56065,14 @@ function tok (n) {
56037
56065
tok('NUMERICIDENTIFIER')
56038
56066
src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*'
56039
56067
tok('NUMERICIDENTIFIERLOOSE')
56040
- src[t.NUMERICIDENTIFIERLOOSE] = '[0-9] +'
56068
+ src[t.NUMERICIDENTIFIERLOOSE] = '\\d +'
56041
56069
56042
56070
// ## Non-numeric Identifier
56043
56071
// Zero or more digits, followed by a letter or hyphen, and then zero or
56044
56072
// more letters, digits, or hyphens.
56045
56073
56046
56074
tok('NONNUMERICIDENTIFIER')
56047
- src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-] *'
56075
+ src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-]' + LETTERDASHNUMBER + ' *'
56048
56076
56049
56077
// ## Main Version
56050
56078
// Three dot-separated numeric identifiers.
@@ -56086,7 +56114,7 @@ src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] +
56086
56114
// Any combination of digits, letters, or hyphens.
56087
56115
56088
56116
tok('BUILDIDENTIFIER')
56089
- src[t.BUILDIDENTIFIER] = '[0-9A-Za-z-] +'
56117
+ src[t.BUILDIDENTIFIER] = LETTERDASHNUMBER + ' +'
56090
56118
56091
56119
// ## Build Metadata
56092
56120
// Plus sign, followed by one or more period-separated build metadata
@@ -56166,6 +56194,7 @@ src[t.COERCE] = '(^|[^\\d])' +
56166
56194
'(?:$|[^\\d])'
56167
56195
tok('COERCERTL')
56168
56196
re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g')
56197
+ safeRe[t.COERCERTL] = new RegExp(makeSafeRe(src[t.COERCE]), 'g')
56169
56198
56170
56199
// Tilde ranges.
56171
56200
// Meaning is "reasonably at or greater than"
@@ -56175,6 +56204,7 @@ src[t.LONETILDE] = '(?:~>?)'
56175
56204
tok('TILDETRIM')
56176
56205
src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+'
56177
56206
re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g')
56207
+ safeRe[t.TILDETRIM] = new RegExp(makeSafeRe(src[t.TILDETRIM]), 'g')
56178
56208
var tildeTrimReplace = '$1~'
56179
56209
56180
56210
tok('TILDE')
@@ -56190,6 +56220,7 @@ src[t.LONECARET] = '(?:\\^)'
56190
56220
tok('CARETTRIM')
56191
56221
src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+'
56192
56222
re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g')
56223
+ safeRe[t.CARETTRIM] = new RegExp(makeSafeRe(src[t.CARETTRIM]), 'g')
56193
56224
var caretTrimReplace = '$1^'
56194
56225
56195
56226
tok('CARET')
@@ -56211,6 +56242,7 @@ src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] +
56211
56242
56212
56243
// this one has to use the /g flag
56213
56244
re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g')
56245
+ safeRe[t.COMPARATORTRIM] = new RegExp(makeSafeRe(src[t.COMPARATORTRIM]), 'g')
56214
56246
var comparatorTrimReplace = '$1$2$3'
56215
56247
56216
56248
// Something like `1.2.3 - 1.2.4`
@@ -56239,6 +56271,14 @@ for (var i = 0; i < R; i++) {
56239
56271
debug(i, src[i])
56240
56272
if (!re[i]) {
56241
56273
re[i] = new RegExp(src[i])
56274
+
56275
+ // Replace all greedy whitespace to prevent regex dos issues. These regex are
56276
+ // used internally via the safeRe object since all inputs in this library get
56277
+ // normalized first to trim and collapse all extra whitespace. The original
56278
+ // regexes are exported for userland consumption and lower level usage. A
56279
+ // future breaking change could export the safer regex only with a note that
56280
+ // all input should have extra whitespace removed.
56281
+ safeRe[i] = new RegExp(makeSafeRe(src[i]))
56242
56282
}
56243
56283
}
56244
56284
@@ -56263,7 +56303,7 @@ function parse (version, options) {
56263
56303
return null
56264
56304
}
56265
56305
56266
- var r = options.loose ? re [t.LOOSE] : re [t.FULL]
56306
+ var r = options.loose ? safeRe [t.LOOSE] : safeRe [t.FULL]
56267
56307
if (!r.test(version)) {
56268
56308
return null
56269
56309
}
@@ -56318,7 +56358,7 @@ function SemVer (version, options) {
56318
56358
this.options = options
56319
56359
this.loose = !!options.loose
56320
56360
56321
- var m = version.trim().match(options.loose ? re [t.LOOSE] : re [t.FULL])
56361
+ var m = version.trim().match(options.loose ? safeRe [t.LOOSE] : safeRe [t.FULL])
56322
56362
56323
56363
if (!m) {
56324
56364
throw new TypeError('Invalid Version: ' + version)
@@ -56763,6 +56803,7 @@ function Comparator (comp, options) {
56763
56803
return new Comparator(comp, options)
56764
56804
}
56765
56805
56806
+ comp = comp.trim().split(/\s+/).join(' ')
56766
56807
debug('comparator', comp, options)
56767
56808
this.options = options
56768
56809
this.loose = !!options.loose
@@ -56779,7 +56820,7 @@ function Comparator (comp, options) {
56779
56820
56780
56821
var ANY = {}
56781
56822
Comparator.prototype.parse = function (comp) {
56782
- var r = this.options.loose ? re [t.COMPARATORLOOSE] : re [t.COMPARATOR]
56823
+ var r = this.options.loose ? safeRe [t.COMPARATORLOOSE] : safeRe [t.COMPARATOR]
56783
56824
var m = comp.match(r)
56784
56825
56785
56826
if (!m) {
@@ -56903,17 +56944,24 @@ function Range (range, options) {
56903
56944
this.loose = !!options.loose
56904
56945
this.includePrerelease = !!options.includePrerelease
56905
56946
56906
- // First, split based on boolean or ||
56947
+ // First reduce all whitespace as much as possible so we do not have to rely
56948
+ // on potentially slow regexes like \s*. This is then stored and used for
56949
+ // future error messages as well.
56907
56950
this.raw = range
56908
- this.set = range.split(/\s*\|\|\s*/).map(function (range) {
56951
+ .trim()
56952
+ .split(/\s+/)
56953
+ .join(' ')
56954
+
56955
+ // First, split based on boolean or ||
56956
+ this.set = this.raw.split('||').map(function (range) {
56909
56957
return this.parseRange(range.trim())
56910
56958
}, this).filter(function (c) {
56911
56959
// throw out any that are not relevant for whatever reason
56912
56960
return c.length
56913
56961
})
56914
56962
56915
56963
if (!this.set.length) {
56916
- throw new TypeError('Invalid SemVer Range: ' + range )
56964
+ throw new TypeError('Invalid SemVer Range: ' + this.raw )
56917
56965
}
56918
56966
56919
56967
this.format()
@@ -56932,28 +56980,27 @@ Range.prototype.toString = function () {
56932
56980
56933
56981
Range.prototype.parseRange = function (range) {
56934
56982
var loose = this.options.loose
56935
- range = range.trim()
56936
56983
// `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
56937
- var hr = loose ? re [t.HYPHENRANGELOOSE] : re [t.HYPHENRANGE]
56984
+ var hr = loose ? safeRe [t.HYPHENRANGELOOSE] : safeRe [t.HYPHENRANGE]
56938
56985
range = range.replace(hr, hyphenReplace)
56939
56986
debug('hyphen replace', range)
56940
56987
// `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
56941
- range = range.replace(re [t.COMPARATORTRIM], comparatorTrimReplace)
56942
- debug('comparator trim', range, re [t.COMPARATORTRIM])
56988
+ range = range.replace(safeRe [t.COMPARATORTRIM], comparatorTrimReplace)
56989
+ debug('comparator trim', range, safeRe [t.COMPARATORTRIM])
56943
56990
56944
56991
// `~ 1.2.3` => `~1.2.3`
56945
- range = range.replace(re [t.TILDETRIM], tildeTrimReplace)
56992
+ range = range.replace(safeRe [t.TILDETRIM], tildeTrimReplace)
56946
56993
56947
56994
// `^ 1.2.3` => `^1.2.3`
56948
- range = range.replace(re [t.CARETTRIM], caretTrimReplace)
56995
+ range = range.replace(safeRe [t.CARETTRIM], caretTrimReplace)
56949
56996
56950
56997
// normalize spaces
56951
56998
range = range.split(/\s+/).join(' ')
56952
56999
56953
57000
// At this point, the range is completely trimmed and
56954
57001
// ready to be split into comparators.
56955
57002
56956
- var compRe = loose ? re [t.COMPARATORLOOSE] : re [t.COMPARATOR]
57003
+ var compRe = loose ? safeRe [t.COMPARATORLOOSE] : safeRe [t.COMPARATOR]
56957
57004
var set = range.split(' ').map(function (comp) {
56958
57005
return parseComparator(comp, this.options)
56959
57006
}, this).join(' ').split(/\s+/)
@@ -57053,7 +57100,7 @@ function replaceTildes (comp, options) {
57053
57100
}
57054
57101
57055
57102
function replaceTilde (comp, options) {
57056
- var r = options.loose ? re [t.TILDELOOSE] : re [t.TILDE]
57103
+ var r = options.loose ? safeRe [t.TILDELOOSE] : safeRe [t.TILDE]
57057
57104
return comp.replace(r, function (_, M, m, p, pr) {
57058
57105
debug('tilde', comp, _, M, m, p, pr)
57059
57106
var ret
@@ -57094,7 +57141,7 @@ function replaceCarets (comp, options) {
57094
57141
57095
57142
function replaceCaret (comp, options) {
57096
57143
debug('caret', comp, options)
57097
- var r = options.loose ? re [t.CARETLOOSE] : re [t.CARET]
57144
+ var r = options.loose ? safeRe [t.CARETLOOSE] : safeRe [t.CARET]
57098
57145
return comp.replace(r, function (_, M, m, p, pr) {
57099
57146
debug('caret', comp, _, M, m, p, pr)
57100
57147
var ret
@@ -57153,7 +57200,7 @@ function replaceXRanges (comp, options) {
57153
57200
57154
57201
function replaceXRange (comp, options) {
57155
57202
comp = comp.trim()
57156
- var r = options.loose ? re [t.XRANGELOOSE] : re [t.XRANGE]
57203
+ var r = options.loose ? safeRe [t.XRANGELOOSE] : safeRe [t.XRANGE]
57157
57204
return comp.replace(r, function (ret, gtlt, M, m, p, pr) {
57158
57205
debug('xRange', comp, ret, gtlt, M, m, p, pr)
57159
57206
var xM = isX(M)
@@ -57228,7 +57275,7 @@ function replaceXRange (comp, options) {
57228
57275
function replaceStars (comp, options) {
57229
57276
debug('replaceStars', comp, options)
57230
57277
// Looseness is ignored here. star is always as loose as it gets!
57231
- return comp.trim().replace(re [t.STAR], '')
57278
+ return comp.trim().replace(safeRe [t.STAR], '')
57232
57279
}
57233
57280
57234
57281
// This function is passed to string.replace(re[t.HYPHENRANGE])
@@ -57554,7 +57601,7 @@ function coerce (version, options) {
57554
57601
57555
57602
var match = null
57556
57603
if (!options.rtl) {
57557
- match = version.match(re [t.COERCE])
57604
+ match = version.match(safeRe [t.COERCE])
57558
57605
} else {
57559
57606
// Find the right-most coercible string that does not share
57560
57607
// a terminus with a more left-ward coercible string.
@@ -57565,17 +57612,17 @@ function coerce (version, options) {
57565
57612
// Stop when we get a match that ends at the string end, since no
57566
57613
// coercible string can be more right-ward without the same terminus.
57567
57614
var next
57568
- while ((next = re [t.COERCERTL].exec(version)) &&
57615
+ while ((next = safeRe [t.COERCERTL].exec(version)) &&
57569
57616
(!match || match.index + match[0].length !== version.length)
57570
57617
) {
57571
57618
if (!match ||
57572
57619
next.index + next[0].length !== match.index + match[0].length) {
57573
57620
match = next
57574
57621
}
57575
- re [t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length
57622
+ safeRe [t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length
57576
57623
}
57577
57624
// leave it in a clean state
57578
- re [t.COERCERTL].lastIndex = -1
57625
+ safeRe [t.COERCERTL].lastIndex = -1
57579
57626
}
57580
57627
57581
57628
if (match === null) {
0 commit comments